diff --git a/src/SharpGLTF.Ext.3DTiles/README.md b/src/SharpGLTF.Ext.3DTiles/README.md new file mode 100644 index 00000000..59770cbb --- /dev/null +++ b/src/SharpGLTF.Ext.3DTiles/README.md @@ -0,0 +1,381 @@ +# SharpGLTF.Ext.3DTiles + +This project contains the implementation of 3D Tiles support for SharpGLTF. + +The following extensions are supported: + +- CESIUM_primitive_outline + +Specs: https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/CESIUM_primitive_outline/README.md + +Samples: https://github.com/CesiumGS/3d-tiles-samples/tree/main/glTF/CESIUM_primitive_outline/BoxPrimitiveOutline + +- EXT_Mesh_Features + +Specs: https://github.com/CesiumGS/glTF/tree/proposal-EXT_mesh_features/extensions/2.0/Vendor/EXT_mesh_features + +Samples: https://github.com/CesiumGS/3d-tiles-samples/blob/main/glTF/EXT_mesh_features + +- EXT_Instance_Features + +Specs: https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_instance_features + +Samples: https://github.com/CesiumGS/3d-tiles-samples/tree/main/glTF/GpuInstancesMetadata + +- Ext_Structural_Metadata + +Specs: https://github.com/CesiumGS/glTF/tree/proposal-EXT_structural_metadata/extensions/2.0/Vendor/EXT_structural_metadata + +Samples: https://github.com/CesiumGS/3d-tiles-samples/tree/main/glTF/EXT_structural_metadata + +Not supported: External schema and min/max/scale/offset properties for StructuralMetadataClassProperty and PropertyAttributeProperty + +## Unit testing + +## Reading 3D Tiles glTF files + +The unit test project contains a set of glTF files that are used to test the implementation of the extensions. The glTF files +are obtained from https://github.com/CesiumGS/3d-tiles-validator/tree/main/specs/data/gltfExtensions. + +## Writing 3D Tiles glTF files + +See the unit test project for examples of how to write glTF files with the extensions. + +The unit tests writes glTF files like the samples from https://github.com/CesiumGS/3d-tiles-samples/tree/main/glTF + +## Validation + +For reading glTF files with 3D Tiles extensions the files should be valid according to a validator. The validator is available at https://github.com/CesiumGS/3d-tiles-validator + +When writing glTF files with 3D Tiles extensions the resulting files should be valid according to the validator. + +## Sample code + +### Reading a 3D Tiles glTF file with metadata + +```csharp + Tiles3DExtensions.RegisterExtensions(); + var model = ModelRoot.Load("sample.gltf"); + var structuralMetadataExtension = model.GetExtension(); + var meshFeaturesExtension = model.LogicalMeshes[0].Primitives[0].GetExtension(); +``` + +## Writing a 3D Tiles glTF file with attribute metadata + +In the following sample a glTF with 1 triangle is created. The triangle contains metadata with +a name column. The name column is set to "this is featureId0". The triangle is assigned featureId 0. + +```csharp + Tiles3DExtensions.RegisterExtensions(); + int featureId = 0; + var material = MaterialBuilder.CreateDefault().WithDoubleSide(true); + + var mesh = new MeshBuilder("mesh"); + var prim = mesh.UsePrimitive(material); + + var vt0 = VertexBuilder.GetVertexWithFeatureId(new Vector3(0, 0, 0), new Vector3(0, 0, 1), featureId); + var vt1 = VertexBuilder.GetVertexWithFeatureId(new Vector3(1, 0, 0), new Vector3(0, 0, 1), featureId); + var vt2 = VertexBuilder.GetVertexWithFeatureId(new Vector3(0, 1, 0), new Vector3(0, 0, 1), featureId); + + prim.AddTriangle(vt0, vt1, vt2); + var scene = new SceneBuilder(); + scene.AddRigidMesh(mesh, Matrix4x4.Identity); + var model = scene.ToGltf2(); + + var rootMetadata = model.UseStructuralMetadata(); + var schema = rootMetadata.UseEmbeddedSchema("schema_001"); + + var schemaClass = schema.UseClassMetadata("triangles"); + + var nameProperty = schemaClass + .UseProperty("name") + .WithStringType(); + + var propertyTable = schemaClass + .AddPropertyTable(1); + + propertyTable + .UseProperty(nameProperty) + .SetValues("this is featureId0"); + + foreach (var primitive in model.LogicalMeshes[0].Primitives) + { + var featureIdAttribute = new FeatureIDBuilder(1, 0, propertyTable); + primitive.AddMeshFeatureIds(featureIdAttribute); + } + + model.SaveGLTF(@"sample.gltf"); +``` + +3D Tiles specific parts in the resulting glTF: + +``` + "extensions": { + "EXT_structural_metadata": { + "propertyTables": [ + { + "class": "triangles", + "count": 1, + "properties": { + "name": { + "stringOffsets": 3, + "values": 2 + } + } + } + ], + "schema": { + "classes": { + "triangles": { + "properties": { + "name": { + "type": "STRING" + } + } + } + }, + "id": "schema_001" + } + } + }, + "extensionsUsed": [ + "EXT_structural_metadata", + "EXT_mesh_features" + ], + "meshes": [ + { + "name": "mesh", + "primitives": [ + { + "extensions": { + "EXT_mesh_features": { + "featureIds": [ + { + "attribute": 0, + "featureCount": 1, + "propertyTable": 0 + } + ] + } + }, + "attributes": { + "POSITION": 0, + "NORMAL": 1, + "_FEATURE_ID_0": 2 + }, + "indices": 3, + "material": 0 + } + ] + } + ], + + ``` + + Sample loaded in Cesium: + + + ![alt text](cesium_sample_metadata_attributes.png) + + ## Writing a 3D Tiles glTF file with texture metadata + + In the following sample a glTF with 2 triangles is created. For visualizing the triangles a texture of a building is used. + A second texture is used containing metadata for storing the metadata values: + + - R channel: Inside temperature + + - G channel: Outside temperature + + - B channel: Humidity + + Using a shader in the client application the metadata values can be visualized. + + ```csharp + Tiles3DExtensions.RegisterExtensions(); + + var img0 = "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"; + var imageBytes0 = Convert.FromBase64String(img0); + var imageBuilder0 = ImageBuilder.From(imageBytes0); + + var img1 = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg=="; + var imageBytes1 = Convert.FromBase64String(img1); + var imageBuilder1 = ImageBuilder.From(imageBytes1); + + var material = MaterialBuilder + .CreateDefault() + .WithMetallicRoughnessShader() + .WithBaseColor(imageBuilder0, new Vector4(1, 1, 1, 1)) + .WithDoubleSide(true) + .WithAlpha(Materials.AlphaMode.OPAQUE) + .WithMetallicRoughness(0, 1) + .WithMetallicRoughness(imageBuilder1); + + var mesh = VBTexture1.CreateCompatibleMesh("mesh"); + var prim = mesh.UsePrimitive(material); + prim.AddTriangle( + new VBTexture1(new VertexPosition(0, 0, 0), new Vector2(0, 1)), + new VBTexture1(new VertexPosition(1, 0, 0), new Vector2(1, 1)), + new VBTexture1(new VertexPosition(0, 1, 0), new Vector2(0, 0))); + + prim.AddTriangle( + new VBTexture1(new VertexPosition(1, 0, 0), new Vector2(1, 1)), + new VBTexture1(new VertexPosition(1, 1, 0), new Vector2(1, 0)), + new VBTexture1(new VertexPosition(0, 1, 0), new Vector2(0, 0))); + + var scene = new SceneBuilder(); + scene.AddRigidMesh(mesh, Matrix4x4.Identity); + var model = scene.ToGltf2(); + + // -------------------------------------------------------------- + + var rootMetadata = model.UseStructuralMetadata(); + var schema = rootMetadata.UseEmbeddedSchema("SimplePropertyTextureSchema"); + + // define schema + + var exampleMetadataClass = schema + .UseClassMetadata("buildingComponents") + .WithName("Building properties"); + + exampleMetadataClass + .UseProperty("insideTemperature") + .WithName("Inside temperature") + .WithUInt8Type(); + + exampleMetadataClass + .UseProperty("outsideTemperature") + .WithName("Outside temperature") + .WithUInt8Type(); + + exampleMetadataClass + .UseProperty("insulation") + .WithName("Insulation Thickness") + .WithUInt8Type() + .WithNormalized(true); + + // define texture property + + var buildingPropertyTexture = exampleMetadataClass.AddPropertyTexture(); + + buildingPropertyTexture.CreateProperty("insideTemperature", model.LogicalTextures[1], new int[] { 0 }); + buildingPropertyTexture.CreateProperty("outsideTemperature", model.LogicalTextures[1], new int[] { 1 }); + buildingPropertyTexture.CreateProperty("insulation", model.LogicalTextures[1], new int[] { 2 }); + + // assign to primitive + + var primitive = model.LogicalMeshes[0].Primitives[0]; + primitive.AddPropertyTexture(buildingPropertyTexture); + + model.SaveGLTF(@"sample.gltf"); + +``` + +3D Tiles specific parts in the resulting glTF: + +``` + "extensions": { + "EXT_structural_metadata": { + "propertyTextures": [ + { + "class": "buildingComponents", + "properties": { + "insideTemperature": { + "index": 1, + "channels": [ + 0 + ] + }, + "outsideTemperature": { + "index": 1, + "channels": [ + 1 + ] + }, + "insulation": { + "index": 1, + "channels": [ + 2 + ] + } + } + } + ], + "schema": { + "classes": { + "buildingComponents": { + "name": "Building properties", + "properties": { + "insideTemperature": { + "componentType": "UINT8", + "name": "Inside temperature", + "type": "SCALAR" + }, + "outsideTemperature": { + "componentType": "UINT8", + "name": "Outside temperature", + "type": "SCALAR" + }, + "insulation": { + "componentType": "UINT8", + "name": "Insulation Thickness", + "normalized": true, + "type": "SCALAR" + } + } + } + }, + "id": "SimplePropertyTextureSchema" + } + } + }, +"meshes": [ + { + "name": "mesh", + "primitives": [ + { + "extensions": { + "EXT_structural_metadata": { + "propertyTextures": [ + 0 + ] + } + }, + "attributes": { + "POSITION": 0, + "TEXCOORD_0": 1 + }, + "indices": 2, + "material": 0 + } + ] + } + ], +``` + +Shader code for visualizing the metadata: + +``` +// Create a custom (fragment) shader that accesses the metadata value with the +// given property name, normalizes it to a value in [0,1] based on the given +// source range, and uses that value as the brightness for the fragment. +function createShader(propertyName, sourceMin, sourceMax) { + const shader = new Cesium.CustomShader({ + fragmentShaderText: ` + void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) + { + float value = float(fsInput.metadata.${propertyName}); + float range = float(${sourceMax}) - float(${sourceMin}); + float brightness = (value - float(${sourceMin})) / range; + material.diffuse = vec3(brightness); + } + `, + }); + return shader; +} + +tileset.customShader = createShader("insideTemperature", 0.0, 255.0); +``` + +Sample loaded in Cesium: + +![alt text](cesium_sample_metadata_texture.png) diff --git a/src/SharpGLTF.Ext.3DTiles/Schema2/ComponentCount.cs b/src/SharpGLTF.Ext.3DTiles/Schema2/ComponentCount.cs new file mode 100644 index 00000000..d3616a15 --- /dev/null +++ b/src/SharpGLTF.Ext.3DTiles/Schema2/ComponentCount.cs @@ -0,0 +1,61 @@ +using SharpGLTF.Schema2.Tiles3D; + +namespace SharpGLTF.Schema2 +{ + public static class ComponentCount + { + public static int ByteSizeForComponentType(DataType? dataType) + { + switch (dataType) + { + case DataType.INT8: + return 1; + case DataType.UINT8: + return 1; + case DataType.INT16: + return 2; + case DataType.UINT16: + return 2; + case DataType.INT32: + return 4; + case DataType.UINT32: + return 4; + case DataType.INT64: + return 8; + case DataType.UINT64: + return 8; + case DataType.FLOAT32: + return 4; + case DataType.FLOAT64: + return 8; + default: return 0; + } + } + + public static int ElementCountForType(ElementType t) + { + switch (t) + { + case ElementType.SCALAR: + case ElementType.STRING: + case ElementType.ENUM: + case ElementType.BOOLEAN: + return 1; + case ElementType.VEC2: + return 2; + case ElementType.VEC3: + return 3; + case ElementType.VEC4: + return 4; + case ElementType.MAT2: + return 4; + case ElementType.MAT3: + return 9; + case ElementType.MAT4: + return 16; + default: return 0; + } + } + + } +} diff --git a/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.FeatureID.cs b/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.FeatureID.cs index 712211c7..b457d9d8 100644 --- a/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.FeatureID.cs +++ b/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.FeatureID.cs @@ -1,95 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Text; +using System.Collections.Generic; using System.Linq; namespace SharpGLTF.Schema2.Tiles3D { using Collections; - /// - /// Mesh Feature Ids - /// - /// - /// Implemented by and - /// - public interface IMeshFeatureIDInfo - { - /// - /// The number of unique features in the attribute or texture. - /// - public int FeatureCount { get; set; } - - /// - /// A value that indicates that no feature is associated with this vertex or texel. - /// - public int? NullFeatureId { get; set; } - - /// - /// An attribute containing feature IDs. When `attribute` and `texture` are omitted the - /// feature IDs are assigned to vertices by their index. - /// - public int? Attribute { get; set; } - - /// - /// A label assigned to this feature ID set. Labels must be alphanumeric identifiers - /// matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. - /// - public string Label { get; set; } - - /// - /// The index of the property table containing per-feature property values. Only applicable when using the `EXT_structural_metadata` extension. - /// - public int? PropertyTableIndex { get; set; } - } - - public sealed class FeatureIDBuilder : IMeshFeatureIDInfo , IEquatable - { - public FeatureIDBuilder(int featureCount, string label = null) - { - FeatureCount = featureCount; - Label = label; - } - - public FeatureIDBuilder(int featureCount, int attribute, string label = null) - { - FeatureCount = featureCount; - Attribute = attribute; - - Label = label; - } - - public FeatureIDBuilder(PropertyTable table, int? attribute = null, string label = null) - { - FeatureCount = table.Count; - Attribute = attribute; - _root = table.LogicalParent; - PropertyTableIndex = table.LogicalIndex; - - Label = label; - } - - private readonly EXTStructuralMetadataRoot _root; - - public int FeatureCount { get; set; } - public int? NullFeatureId { get; set; } - public int? Attribute { get; set; } - public string Label { get; set; } - public int? PropertyTableIndex { get; set; } - - public bool Equals(IMeshFeatureIDInfo other) - { - if (other == null) return false; - if (this.FeatureCount != other.FeatureCount) return false; - if (this.NullFeatureId != other.NullFeatureId) return false; - if (this.Attribute != other.Attribute) return false; - if (this.Label != other.Label) return false; - if (this.PropertyTableIndex != other.PropertyTableIndex) return false; - - return true; - } - } - /// /// Use to create an instance of this class. /// @@ -97,17 +12,6 @@ public partial class MeshExtInstanceFeatureID : IChildOfList /// Gets a texture containing feature IDs. /// @@ -330,6 +231,8 @@ private ModelRoot _GetModelRoot() return LogicalParent?.LogicalParent?.LogicalParent?.LogicalParent?.LogicalParent; } + public IReadOnlyList GetChannels() => _channels; + public void SetChannels(IReadOnlyList channels) { Guard.NotNullOrEmpty(channels, nameof(channels)); diff --git a/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.Features.cs b/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.Features.cs index c2db0273..161b1486 100644 --- a/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.Features.cs +++ b/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.Features.cs @@ -24,7 +24,7 @@ internal static void ValidateFeatureIdReferences(this IMeshFeatureIDInfo feature internal static void ValidateFeatureIdContent(this IMeshFeatureIDInfo featureId) { - Guard.MustBeGreaterThanOrEqualTo((int)featureId.FeatureCount, 1, nameof(featureId.FeatureCount)); + Guard.MustBeGreaterThanOrEqualTo(featureId.FeatureCount, 1, nameof(featureId.FeatureCount)); if (featureId.NullFeatureId.HasValue) { @@ -35,7 +35,6 @@ internal static void ValidateFeatureIdContent(this IMeshFeatureIDInfo featureId) var regex = "^[a-zA-Z_][a-zA-Z0-9_]*$"; Guard.IsTrue(System.Text.RegularExpressions.Regex.IsMatch(featureId.Label, regex), nameof(featureId.Label)); } - if (featureId.Attribute.HasValue) { Guard.MustBeGreaterThanOrEqualTo((int)featureId.Attribute, 0, nameof(featureId.Attribute)); @@ -68,18 +67,28 @@ public static MeshExtInstanceFeatureID[] AddInstanceFeatureIds(this Node node, p /// /// Adds the FeatureIds to a MeshPrimitive /// - public static MeshExtMeshFeatureID[] AddMeshFeatureIds(this MeshPrimitive primitive, params (IMeshFeatureIDInfo fid, Texture tex, IReadOnlyList channels)[] featureIds) + public static MeshExtMeshFeatureID[] AddMeshFeatureIds(this MeshPrimitive primitive, params IMeshFeatureIDInfo[] fids) { - if (featureIds == null || featureIds.Length == 0) { primitive.RemoveExtensions(); return Array.Empty(); } + if (fids == null || fids.Length == 0) { primitive.RemoveExtensions(); return Array.Empty(); } var ext = primitive.UseExtension(); - var result = new MeshExtMeshFeatureID[featureIds.Length]; + var result = new MeshExtMeshFeatureID[fids.Length]; for (int i = 0; i < result.Length; ++i) { - var (fid, tex, channels) = featureIds[i]; - result[i] = ext.CreateFeatureID(fid, tex, channels); + var fid = fids[i]; + result[i] = ext.CreateFeatureID(fid); + + if (fid is FeatureIDBuilder builder && builder.Texture != null) + { + var texture = result[i].UseTexture(); + texture.Texture = builder.Texture; + if (builder.Channels != null) + { + texture.SetChannels(builder.Channels); + } + } } return result; @@ -226,7 +235,7 @@ protected override IEnumerable GetLogicalChildren() #region API - public MeshExtMeshFeatureID CreateFeatureID(IMeshFeatureIDInfo properties, Texture texture = null, IReadOnlyList texChannels = null) + public MeshExtMeshFeatureID CreateFeatureID(IMeshFeatureIDInfo properties) { var instance = CreateFeatureID(); @@ -236,13 +245,6 @@ public MeshExtMeshFeatureID CreateFeatureID(IMeshFeatureIDInfo properties, Textu instance.Attribute = properties.Attribute; instance.PropertyTableIndex = properties.PropertyTableIndex; - if (texture != null) - { - var texInfo = instance.UseTexture(); - texInfo.Texture = texture; - if (texChannels != null) texInfo.SetChannels(texChannels); - } - return instance; } @@ -264,7 +266,8 @@ protected override void OnValidateReferences(ValidationContext validate) if (featureId.Attribute.HasValue) { var expectedVertexAttribute = $"_FEATURE_ID_{featureId.Attribute}"; - Guard.NotNull(_meshPrimitive.GetVertexAccessor(expectedVertexAttribute), expectedVertexAttribute); + var featureIdVertex = _meshPrimitive.GetVertexAccessor(expectedVertexAttribute); + Guard.NotNull(featureIdVertex, expectedVertexAttribute, $"The primitive should have custom vertex attribute {expectedVertexAttribute}."); } featureId.ValidateFeatureIdReferences(_meshPrimitive.LogicalParent.LogicalParent); @@ -274,7 +277,7 @@ protected override void OnValidateReferences(ValidationContext validate) if (texture != null) { var expectedTexCoordAttribute = $"TEXCOORD_{texture.TextureCoordinate}"; - Guard.NotNull(_meshPrimitive.GetVertexAccessor(expectedTexCoordAttribute), expectedTexCoordAttribute); + Guard.NotNull(_meshPrimitive.GetVertexAccessor(expectedTexCoordAttribute), expectedTexCoordAttribute, $"The primitive should have texture {expectedTexCoordAttribute}."); var modelRoot = _meshPrimitive.LogicalParent.LogicalParent; validate.IsNullOrIndex(nameof(texture), texture.TextureCoordinate, modelRoot.LogicalTextures); @@ -286,14 +289,81 @@ protected override void OnValidateReferences(ValidationContext validate) protected override void OnValidateContent(ValidationContext validate) { - var extMeshFeatures = _meshPrimitive.Extensions.Where(item => item is MeshExtMeshFeatures).FirstOrDefault(); - validate.NotNull(nameof(extMeshFeatures), extMeshFeatures); validate.NotNull(nameof(FeatureIds), _featureIds); validate.IsTrue(nameof(FeatureIds), _featureIds.Count > 0, "FeatureIds has items"); foreach (var featureId in _featureIds) { featureId.ValidateFeatureIdContent(); + + if (featureId.Attribute != null) + { + var expectedVertexAttribute = $"_FEATURE_ID_{featureId.Attribute}"; + var vertex = _meshPrimitive.GetVertexAccessor(expectedVertexAttribute); + Guard.IsTrue(!vertex.Normalized, expectedVertexAttribute, $"The custom vertex attribute {expectedVertexAttribute} should not be normalized."); + + var distinctFeatureIds = vertex.AsScalarArray().Distinct().ToList(); + + if (featureId.NullFeatureId.HasValue) + { + distinctFeatureIds.Remove(featureId.NullFeatureId.Value); + } + + if (distinctFeatureIds.Min() < 0) + { + Guard.IsTrue(distinctFeatureIds.Min() >= 0, nameof(distinctFeatureIds), $"FeatureIds must be equal or larger than 0, but contains {distinctFeatureIds.Min()}"); + } + + var count = distinctFeatureIds.Count(); + + // FeatureCount must be greater or equal to the number of distinct feature ids + Guard.IsTrue(featureId.FeatureCount >= count, $"Mismatch between FeatureCount ({featureId.FeatureCount}) and Feature Attribute ({count})"); + + if (featureId.PropertyTableIndex.HasValue) + { + var root = _meshPrimitive.LogicalParent.LogicalParent; + var metadataExtension = root.GetExtension(); + var propertyTable = metadataExtension.PropertyTables[featureId.PropertyTableIndex.Value]; + var propertyCount = propertyTable.Count; + Guard.IsTrue(distinctFeatureIds.Max() <= propertyCount - 1, nameof(propertyCount), + $"The feature ID refers to a property table with {propertyCount} rows, so the feature IDs must be in the range [0,{propertyCount-1}], but the feature ID attribute contains values [{distinctFeatureIds.Min()},{distinctFeatureIds.Max()}]"); + } + + + } + var texture = featureId.GetTexture(); + if (texture != null) + { + var expectedTexCoordAttribute = $"TEXCOORD_{texture.TextureCoordinate}"; + var vertex = _meshPrimitive.GetVertexAccessor(expectedTexCoordAttribute); + var distinctFeatureIds = vertex.AsVector2Array().Count(); + + Guard.IsTrue(featureId.FeatureCount == distinctFeatureIds, $"Mismatch between FeatureCount ({featureId.FeatureCount}) and Feature Texture ({distinctFeatureIds})"); + + var modelRoot = _meshPrimitive.LogicalParent.LogicalParent; + + var samplers = modelRoot.LogicalTextureSamplers; + foreach (var sampler in samplers) + { + Guard.IsTrue(sampler.MagFilter == TextureInterpolationFilter.NEAREST, $"Texture magnification filter must be 9728 (NEAREST) but is set to {sampler.MagFilter}"); + Guard.IsTrue(sampler.MinFilter == TextureMipMapFilter.NEAREST, $"Texture minification filtering must be 9728 (NEAREST) but is set to {sampler.MinFilter}"); + } + + // check on channels as workaround + // better solution: read the channels of the used texture using image library + var logicalTexture = modelRoot.LogicalTextures[texture.TextureCoordinate]; + // var image = logicalTexture.PrimaryImage; + var channels = texture.GetChannels(); + + // chack that the length of channels list is maximum 4 + Guard.IsTrue(channels.Count <= 4, $"The number of channels must be maximum 4 but is {channels.Count}"); + + // check that value in channels is minimum 0 and maximum 3 + foreach (var channel in channels) + { + Guard.IsTrue(channel >= 0 && channel <= 3, $"Channel value must be between 0 and 3 but has channel {channel}"); + } + } } base.OnValidateContent(validate); @@ -302,5 +372,5 @@ protected override void OnValidateContent(ValidationContext validate) #endregion } - } + } } diff --git a/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.StructuralMetadataPrimitive.cs b/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.StructuralMetadataPrimitive.cs index 571999be..77286a54 100644 --- a/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.StructuralMetadataPrimitive.cs +++ b/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.StructuralMetadataPrimitive.cs @@ -10,12 +10,6 @@ namespace SharpGLTF.Schema2 partial class Tiles3DExtensions { - // TODO: PropertyTexture is taken from a Schema, but it is possible the schema is an external file, - // in which case we could not have a PopertyTexture, just a blind ID - - // Solution1: enforce loading the schema as part of the memory document - // Solution2: allow the API to be OneOf - public static void AddPropertyTexture(this MeshPrimitive primitive, PropertyTexture texture) { var ext = primitive.UseExtension(); @@ -75,11 +69,11 @@ public PropertyTexture GetTexture(int index) public void AddTexture(PropertyTexture texture) { Guard.NotNull(texture, nameof(texture)); - + var metadata = _GetModelRoot().UseExtension(); var properties = metadata.PropertyTextures; Guard.IsTrue(properties.Contains(texture), nameof(texture)); - + _propertyTextures.Add(texture.LogicalIndex); } @@ -97,11 +91,11 @@ public PropertyAttribute GetAttribute(int index) public void AddAttribute(PropertyAttribute attribute) { Guard.NotNull(attribute, nameof(attribute)); - + var metadata = _GetModelRoot().UseExtension(); var properties = metadata.PropertyAttributes; Guard.IsTrue(properties.Contains(attribute), nameof(attribute)); - + _propertyAttributes.Add(attribute.LogicalIndex); } @@ -112,22 +106,187 @@ public void AddAttribute(PropertyAttribute attribute) protected override void OnValidateReferences(ValidationContext validate) { var rootMetadata = _GetModelRoot().GetExtension(); + Guard.NotNull(rootMetadata, nameof(rootMetadata), "EXT_Structural_Metadata extension missing in root"); + + ValidatePropertyTexturesReferences(validate, rootMetadata); + + ValidatePropertyAttributesReferences(validate, rootMetadata); + + base.OnValidateReferences(validate); + } + + protected override void OnValidateContent(ValidationContext validate) + { + var rootMetadata = _GetModelRoot().GetExtension(); + var propertyTextures = rootMetadata.PropertyTextures; + + ValidatePropertyTexturesContent(rootMetadata, propertyTextures); + + ValidatePropertyAttributesContent(rootMetadata); + + base.OnValidateContent(validate); + } + + private void ValidatePropertyAttributesReferences(ValidationContext validate, EXTStructuralMetadataRoot rootMetadata) + { + foreach (var propertyAttribute in _propertyAttributes) + { + var propertyAttributes = rootMetadata.PropertyAttributes; + validate.IsNullOrIndex(nameof(propertyAttribute), propertyAttribute, propertyAttributes); + + var schema = rootMetadata.Schema; + var schemaAttribute = propertyAttributes[propertyAttribute]; + + var className = schemaAttribute.ClassName; + Guard.NotNull(schema, nameof(schema), "EXT_Structural_Metadata extension missing schema"); + schema.Classes.TryGetValue(className, out var classDefinition); + Guard.NotNull(classDefinition, nameof(classDefinition), $"EXT_Structural_Metadata extension missing class definition for {className}"); + + foreach (var property in schemaAttribute.Properties) + { + var expectedVertexAttribute = property.Value.Attribute; + Guard.NotNull(meshPrimitive.GetVertexAccessor(expectedVertexAttribute), expectedVertexAttribute, $"The primitive should have custom vertex attribute {expectedVertexAttribute}."); + + var key = property.Key; + + classDefinition.Properties.TryGetValue(key, out var propertyDefinition); + Guard.NotNull(propertyDefinition, nameof(propertyDefinition), $"EXT_Structural_Metadata extension missing property definition for {key}"); + + Guard.IsTrue(propertyDefinition.Array == false, nameof(propertyDefinition.Array), $"The property '{property.Key}' is an array, which is not supported for property attributes"); + + if (propertyDefinition.Type == ElementType.ENUM) + { + var enumType = propertyDefinition.EnumType; + // Get the enum from the schema + var enumDefinition = schema.Enums[enumType]; + Guard.NotNull(enumDefinition, nameof(enumDefinition), $"EXT_Structural_Metadata extension missing enum definition for {enumType}"); + } + } + } + } + + private void ValidatePropertyTexturesReferences(ValidationContext validate, EXTStructuralMetadataRoot rootMetadata) + { + var propertyTextures = rootMetadata.PropertyTextures; + // Scan textures foreach (var propertyTexture in _propertyTextures) { - var propertyTextures = rootMetadata.PropertyTextures; validate.IsNullOrIndex(nameof(propertyTexture), propertyTexture, propertyTextures); + + var schemaTexture = propertyTextures[propertyTexture]; + var className = schemaTexture.ClassName; + foreach (var property in schemaTexture.Properties) + { + var textureCoordinate = property.Value.TextureCoordinate; + // Guard the meshprimitive has the texture coordinate attribute + var expectedVertexAttribute = "TEXCOORD_" + textureCoordinate; + Guard.NotNull(meshPrimitive.GetVertexAccessor(expectedVertexAttribute), nameof(textureCoordinate), $"The primitive should have texture coordinate attribute {textureCoordinate}."); + + var texture = property.Value.Texture; + Guard.NotNull(texture, nameof(texture), $"The primitive should have texture {texture}."); + } } + } + private void ValidatePropertyAttributesContent(EXTStructuralMetadataRoot rootMetadata) + { foreach (var propertyAttribute in _propertyAttributes) { var propertyAttributes = rootMetadata.PropertyAttributes; - validate.IsNullOrIndex(nameof(propertyAttribute), propertyAttribute, propertyAttributes); + var schema = rootMetadata.Schema; + var schemaAttribute = propertyAttributes[propertyAttribute]; + + var className = schemaAttribute.ClassName; + schema.Classes.TryGetValue(className, out var classDefinition); + + foreach (var property in schemaAttribute.Properties) + { + var key = property.Key; + + var acc = property.Value.Attribute; + var vertexAccessor = meshPrimitive.GetVertexAccessor(acc); + + // Todo: check min, max, scale, offset of propertyAttributeProperty + + classDefinition.Properties.TryGetValue(key, out var propertyDefinition); + + // Todo: check min, max, scale, offset of StructuralMetadaClassProperty + + Guard.IsTrue(propertyDefinition.Array == false, nameof(propertyDefinition.Array), $"The property '{property.Key}' is an array, which is not supported for property attributes"); + + Guard.IsTrue(propertyDefinition.Type != ElementType.STRING, nameof(propertyDefinition.Type), + $"The property '{property.Key}' has the type 'STRING', which is not supported for property attributes"); + if (propertyDefinition.Type == ElementType.SCALAR) + { + var allowedComponentTypes = new List() + { + DataType.INT8,DataType.UINT8,DataType.INT16,DataType.UINT16,DataType.FLOAT32, + }; + + Guard.IsTrue(allowedComponentTypes.Contains(propertyDefinition.ComponentType), nameof(propertyDefinition.ComponentType), + $"The property '{property.Key}' has the component type {propertyDefinition.ComponentType}, but the type must be one of INT8,UINT8,INT16,UINT16,FLOAT32 for property attribute"); + } + else if (propertyDefinition.Type == ElementType.ENUM) + { + var enumType = propertyDefinition.EnumType; + schema.Enums.TryGetValue(enumType, out var enumDefinition); + var valueType = enumDefinition.ValueType; + var allowedIntegerTypes = new List() + { + IntegerType.INT8,IntegerType.UINT8,IntegerType.INT16,IntegerType.UINT16 + }; + Guard.IsTrue(allowedIntegerTypes.Contains(valueType), nameof(valueType), + $"The enumeration '{property.Key}' has the value type {valueType}, but the type must be one of INT8,UINT8,INT16,UINT16 for property attribute"); + } + } } + } - base.OnValidateReferences(validate); - } + private void ValidatePropertyTexturesContent(EXTStructuralMetadataRoot rootMetadata, IReadOnlyList propertyTextures) + { + foreach (var propertyTexture in _propertyTextures) + { + var schemaTexture = propertyTextures[propertyTexture]; + + var className = schemaTexture.ClassName; + foreach (var property in schemaTexture.Properties) + { + // use for validation of texture + // var textureCoordinate = property.Value.TextureCoordinate; + // var expectedVertexAttribute = "TEXCOORD_" + textureCoordinate; + + var schemaProperty = rootMetadata.Schema.Classes[className].Properties[property.Key]; + + Guard.IsTrue(schemaProperty.Type != ElementType.STRING, nameof(schemaProperty.Type), + $"The property '{property.Key}' has the type 'STRING', which is not supported for property textures"); + + if (schemaProperty.Array) + { + Guard.IsTrue(schemaProperty.Count != null, nameof(schemaProperty.Array), + $"The property '{property.Key}' is a variable-length array, which is not supported for property textures"); + } + + // todo: check used values in texture against min, max (using scale and offset) + // var min = schemaProperty.Min; + // var max = schemaProperty.Max; + // var scale = schemaProperty.Scale; + // var offset = schemaProperty.Offset; + + var channels = property.Value.Channels; + var elementCount = ComponentCount.ElementCountForType(schemaProperty.Type); + if (schemaProperty.ComponentType != null) + { + var componentByteSize = ComponentCount.ByteSizeForComponentType(schemaProperty.ComponentType); + var elementByteSize = elementCount * componentByteSize; + var totalByteSize = channels.Count * elementByteSize; + Guard.IsTrue(totalByteSize == channels.Count, nameof(totalByteSize), + $"The property '{property.Key}' has the component type {schemaProperty.ComponentType}, with a size of {componentByteSize} bytes, and the type {schemaProperty.Type} with {channels.Count} components, resulting in {totalByteSize} bytes per element, but the number of channels in the property texture property was {channels.Count}"); + } + } + } + } #endregion } } diff --git a/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.StructuralMetadataRoot.cs b/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.StructuralMetadataRoot.cs index b874143b..c2a0d479 100644 --- a/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.StructuralMetadataRoot.cs +++ b/src/SharpGLTF.Ext.3DTiles/Schema2/Ext.StructuralMetadataRoot.cs @@ -11,14 +11,16 @@ namespace SharpGLTF.Schema2 using Collections; using Memory; using Validation; - using Tiles3D; + using Tiles3D; + using System.Numerics; + using System.Text.Json.Nodes; partial class Tiles3DExtensions { public static EXTStructuralMetadataRoot UseStructuralMetadata(this ModelRoot modelRoot) { return modelRoot.UseExtension(); - } + } } namespace Tiles3D @@ -60,11 +62,13 @@ protected override IEnumerable GetLogicalChildren() #region properties + /** internal string SchemaUri { get => _schemaUri; set { _schemaUri = value; } } + */ internal StructuralMetadataSchema Schema { @@ -95,14 +99,23 @@ public StructuralMetadataSchema UseEmbeddedSchema(string id) return schema; } + /** + // Sets the schema to use an external schema, returns an empty schema to used for adding schema properties + public StructuralMetadataSchema UseExternalSchema(Uri uri) + { + SchemaUri = uri.ToString(); + return new StructuralMetadataSchema(); + } + */ + public StructuralMetadataSchema UseEmbeddedSchema() { - this.SchemaUri = null; + // SchemaUri = null; if (_schema == null) GetChildSetter(this).SetProperty(ref _schema, new StructuralMetadataSchema()); return _schema; - } + } public PropertyAttribute AddPropertyAttribute(StructuralMetadataClass schemaClass) { @@ -116,18 +129,18 @@ public PropertyAttribute AddPropertyAttribute() var prop = new PropertyAttribute(); _propertyAttributes.Add(prop); return prop; - } + } - public PropertyTable AddPropertyTable(StructuralMetadataClass schemaClass, int? featureCount = null, string name = null) + public PropertyTable AddPropertyTable(StructuralMetadataClass schemaClass, int featureCount, string name = null) { var table = AddPropertyTable(); table.ClassInstance = schemaClass; - if (featureCount != null) table.Count = featureCount.Value; + table.Count = featureCount; table.Name = name; return table; } - public PropertyTable AddPropertyTable() + private PropertyTable AddPropertyTable() { var prop = new PropertyTable(); _propertyTables.Add(prop); @@ -137,7 +150,7 @@ public PropertyTable AddPropertyTable() public PropertyTexture AddPropertyTexture(StructuralMetadataClass schemaClass) { var prop = AddPropertyTexture(); - prop.ClassInstance = schemaClass; + prop.ClassInstance = schemaClass; return prop; } @@ -146,7 +159,7 @@ public PropertyTexture AddPropertyTexture() var prop = new PropertyTexture(); _propertyTextures.Add(prop); return prop; - } + } #endregion @@ -154,6 +167,13 @@ public PropertyTexture AddPropertyTexture() protected override void OnValidateReferences(ValidationContext validate) { + var root = LogicalParent.GetExtension(); + Guard.MustBeNull(root._schemaUri, nameof(root._schemaUri), + "SchemaUri must be null, use embedded achema to set the schema"); + + // Guard schema is null + Guard.NotNull(Schema, nameof(Schema), "Schema must be defined"); + foreach (var propertyTexture in PropertyTextures) { foreach (var propertyTextureProperty in propertyTexture.Properties) @@ -249,8 +269,8 @@ protected override void OnValidateContent(ValidationContext result) } // Check one of schema or schemaUri is defined, but not both - Guard.IsFalse(Schema != null && SchemaUri != null, "Schema/SchemaUri", "Schema and SchemaUri cannot both be defined"); - Guard.IsFalse(Schema == null && SchemaUri == null, "Schema/SchemaUri", "One of Schema and SchemaUri must be defined"); + // Guard.IsFalse(Schema != null && SchemaUri != null, "Schema/SchemaUri", "Schema and SchemaUri cannot both be defined"); + // Guard.IsFalse(Schema == null && SchemaUri == null, "Schema/SchemaUri", "One of Schema and SchemaUri must be defined"); base.OnValidateContent(result); } @@ -313,7 +333,7 @@ public StructuralMetadataClass ClassInstance { return schema.Classes[ClassName]; } - else return null; + else return null; } set { @@ -338,7 +358,7 @@ public PropertyTextureProperty CreateProperty(string key, Texture texture, IRead return property; } - public PropertyTextureProperty CreateProperty(string key) + private PropertyTextureProperty CreateProperty(string key) { var property = new PropertyTextureProperty(); _properties[key] = property; @@ -387,7 +407,7 @@ public IReadOnlyList Channels _channels.Clear(); _channels.AddRange(value); } - } + } public Schema2.Texture Texture { @@ -517,6 +537,31 @@ public string Attribute set => _attribute = value; } + /** Commented out for now, as it is not supported + public JsonNode Min + { + get => _min; + set => _min = value; + } + + public JsonNode Max + { + get => _max; + set => _max = value; + } + + public JsonNode Scale + { + get => _scale; + set => _scale = value; + } + + public JsonNode Offset + { + get => _offset; + set => _offset = value; + } + */ #endregion } @@ -531,7 +576,7 @@ internal PropertyTable() _properties = new ChildrenDictionary(this); _count = _countMinimum; - } + } protected override IEnumerable GetLogicalChildren() { @@ -589,7 +634,7 @@ public string Name { get => _name; set => _name = value; - } + } public int Count { @@ -619,7 +664,7 @@ public PropertyTableProperty UseProperty(string key) value = new PropertyTableProperty(); _properties[key] = value; return value; - } + } #endregion } @@ -672,35 +717,53 @@ public int? StringOffsets private ModelRoot _GetModelRoot() => LogicalParent.LogicalParent.LogicalParent; - public void SetValues2D(List> values, bool CreateArrayOffsets = true) + public void SetArrayValues(List> values) { + Guard.IsTrue(values.Count == LogicalParent.Count, nameof(values), $"Values must have length {LogicalParent.Count}"); + + var className = LogicalParent.ClassName; + var metadataProperty = GetProperty(className, LogicalKey); + + metadataProperty.Array = true; + var root = _GetModelRoot(); - + int logicalIndex = GetBufferView(root, values); - this.Values = logicalIndex; + Values = logicalIndex; - if (CreateArrayOffsets) + var hasVariableLength = HasVariableLength(values); + + if (HasVariableLength(values) || typeof(T) == typeof(string)) { + // if the array has items of variable length, create arraysOffsets bufferview var arrayOffsets = BinaryTable.GetArrayOffsets(values); int logicalIndexOffsets = GetBufferView(root, arrayOffsets); - this.ArrayOffsets = logicalIndexOffsets; + 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(root, stringOffsets); - this.StringOffsets = offsets; + StringOffsets = offsets; } - } + } + else + { + metadataProperty.Count = values[0].Count; + } } - public void SetValues1D(params T[] values) + public void SetValues(params T[] values) { + Guard.IsTrue(values.Length == LogicalParent.Count, nameof(values), $"Values must have length {LogicalParent.Count}"); + var className = LogicalParent.ClassName; + GetProperty(className, LogicalKey); + var root = _GetModelRoot(); - + int logicalIndex = GetBufferView(root, values); - this.Values = logicalIndex; + Values = logicalIndex; if (typeof(T) == typeof(string)) { @@ -710,8 +773,116 @@ public void SetValues1D(params T[] values) var stringOffsets = BinaryTable.GetStringOffsets(stringvalues); int offsets = GetBufferView(root, stringOffsets); - this.StringOffsets = offsets; - } + StringOffsets = offsets; + } + } + + private StructuralMetadataClassProperty GetProperty(string className, string key) + { + var metadataClass = LogicalParent.LogicalParent.Schema.Classes[className]; + Guard.IsTrue(metadataClass != null, nameof(className), $"Schema class {className} must be defined"); + metadataClass.Properties.TryGetValue(key, out var metadataProperty); + Guard.IsTrue(metadataProperty != null, nameof(key), $"Property {key} in {className} must be defined"); + + CheckElementTypes(metadataProperty); + + return metadataProperty; + } + + private bool HasVariableLength(List> values) + { + int length = values[0].Count; + for (int i = 1; i < values.Count; i++) + { + if (values[i].Count != length) return true; + } + return false; + } + + + private void CheckElementTypes(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(componentType); + } + else if (elementType == ELEMENTTYPE.STRING) + { + Guard.IsTrue(typeof(T) == typeof(string), nameof(T), $"String type of property {LogicalKey} must be string"); + } + else if (elementType == ELEMENTTYPE.BOOLEAN) + { + Guard.IsTrue(typeof(T) == typeof(bool), nameof(T), $"Boolean type of property {LogicalKey} must beboolean"); + } + else if (elementType == ELEMENTTYPE.VEC2) + { + Guard.IsTrue(typeof(T) == typeof(Vector2), nameof(T), $"Vector2 type of property {LogicalKey} must be Vector2"); + } + else if (elementType == ELEMENTTYPE.VEC3) + { + Guard.IsTrue(typeof(T) == typeof(Vector3), nameof(T), $"Vector3 type of property {LogicalKey} must be Vector3"); + } + else if (elementType == ELEMENTTYPE.VEC3) + { + Guard.IsTrue(typeof(T) == typeof(Vector4), nameof(T), $"Vector4 type of property {LogicalKey} must be Vector4"); + } + // todo: add MAT2, MAT3 + else if (elementType == ELEMENTTYPE.MAT4) + { + Guard.IsTrue(typeof(T) == typeof(Matrix4x4), nameof(T), $"Matrix4x4 type of property {LogicalKey} must be Matrix4x4"); + } + } + + private void CheckScalarTypes(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(ModelRoot model, IReadOnlyList values) @@ -764,7 +935,7 @@ protected override IEnumerable GetLogicalChildren() void IChildOf.SetLogicalParent(EXTStructuralMetadataRoot parent) { - LogicalParent = parent; + LogicalParent = parent; } #endregion @@ -814,7 +985,7 @@ public StructuralMetadataClass UseClassMetadata(string key) public StructuralMetadataEnum UseEnumMetadata(string key, params (string name, int value)[] enumValues) { var enumType = UseEnumMetadata(key); - foreach(var (name, value) in enumValues) + foreach (var (name, value) in enumValues) { enumType.AddEnum(name, value); } @@ -864,6 +1035,7 @@ void IChildOfDictionary.SetLogicalParent(StructuralMet public IReadOnlyList Values => _values; + public string Name { get => _name; @@ -875,6 +1047,11 @@ public string Description set => _description = value; } + public IntegerType? ValueType + { + get => _valueType; + } + #endregion #region API @@ -991,10 +1168,15 @@ public string Description #region API - public StructuralMetadataClass WithNameAndDesc(string name, string desc = null) + public StructuralMetadataClass WithName(string name) + { + Name = name; + return this; + } + + public StructuralMetadataClass WithDescription(string description) { - this.Name = name; - this.Description = desc; + Description = description; return this; } @@ -1017,7 +1199,7 @@ public PropertyAttribute AddPropertyAttribute() return LogicalParent.LogicalParent.AddPropertyAttribute(this); } - public PropertyTable AddPropertyTable(int? featureCount = null, string name = null) + public PropertyTable AddPropertyTable(int featureCount, string name = null) { return LogicalParent.LogicalParent.AddPropertyTable(this, featureCount, name); } @@ -1057,7 +1239,7 @@ public string Description set => _description = value; } - public ELEMENTTYPE Type + internal ELEMENTTYPE Type { get => _type; set => _type = value; @@ -1066,7 +1248,7 @@ public ELEMENTTYPE Type public string EnumType { get => _enumType; - set => _enumType = value; + // set => _enumType = value; } public DATATYPE? ComponentType @@ -1099,50 +1281,201 @@ public int? Count set => _count = value; } + /** Commented out for now, as it is not supported + public JsonNode Min + { + get => _min; + set => _min = value; + } + + public JsonNode Max + { + get => _max; + set => _max = value; + } + + public JsonNode Scale + { + get => _scale; + set => _scale = value; + } + + public JsonNode Offset + { + get => _offset; + set => _offset = value; + } + */ + + #endregion #region API - public StructuralMetadataClassProperty WithNameAndDesc(string name, string desc = null) + + public StructuralMetadataClassProperty WithName(string name) + { + Name = name; + return this; + } + + public StructuralMetadataClassProperty WithDescription(string description) + { + Description = description; + return this; + } + + public StructuralMetadataClassProperty WithStringType() + { + Type = ElementType.STRING; + return this; + } + + public StructuralMetadataClassProperty WithBooleanType() + { + Type = ElementType.BOOLEAN; + return this; + } + + public StructuralMetadataClassProperty WithUInt8Type() + { + Type = ELEMENTTYPE.SCALAR; + ComponentType = DATATYPE.UINT8; + return this; + } + + public StructuralMetadataClassProperty WithInt8Type() + { + Type = ELEMENTTYPE.SCALAR; + ComponentType = DATATYPE.INT8; + return this; + } + + public StructuralMetadataClassProperty WithUInt16Type() + { + Type = ELEMENTTYPE.SCALAR; + ComponentType = DATATYPE.UINT16; + return this; + } + + public StructuralMetadataClassProperty WithInt16Type() + { + Type = ELEMENTTYPE.SCALAR; + ComponentType = DATATYPE.INT16; + return this; + } + + public StructuralMetadataClassProperty WithUInt32Type() + { + Type = ELEMENTTYPE.SCALAR; + ComponentType = DATATYPE.UINT32; + return this; + } + + public StructuralMetadataClassProperty WithInt32Type() + { + Type = ELEMENTTYPE.SCALAR; + ComponentType = DATATYPE.INT32; + return this; + } + + public StructuralMetadataClassProperty WithUInt64Type() + { + Type = ELEMENTTYPE.SCALAR; + ComponentType = DATATYPE.UINT64; + return this; + } + + public StructuralMetadataClassProperty WithInt64Type() { - this.Name = name; - this.Description = desc; + Type = ELEMENTTYPE.SCALAR; + ComponentType = DATATYPE.INT64; return this; } - public StructuralMetadataClassProperty WithValueType(ELEMENTTYPE etype, DATATYPE? ctype = null, bool normalized = false) + public StructuralMetadataClassProperty WithFloat32Type() { - this.Type = etype; - this.ComponentType = ctype; - this.Normalized = normalized; - this.Array = false; + Type = ELEMENTTYPE.SCALAR; + ComponentType = DATATYPE.FLOAT32; return this; } - public StructuralMetadataClassProperty WithArrayType(ELEMENTTYPE etype, DATATYPE? ctype = null, bool normalized = false, int? count = null) + public StructuralMetadataClassProperty WithFloat64Type() { - this.Type = etype; - this.ComponentType = ctype; - this.Normalized = normalized; - this.Array = true; - this.Count = count; + Type = ELEMENTTYPE.SCALAR; + ComponentType = DATATYPE.FLOAT64; return this; } - public StructuralMetadataClassProperty WithEnumArrayType(StructuralMetadataEnum enumType, int? count = null) + + public StructuralMetadataClassProperty WithVector3Type() + { + Type = ElementType.VEC3; + ComponentType = DataType.FLOAT32; + return this; + } + + public StructuralMetadataClassProperty WithMatrix4x4Type() { - return WithEnumArrayType(enumType.LogicalKey, count); + Type = ElementType.MAT4; + ComponentType = DataType.FLOAT32; + return this; } - public StructuralMetadataClassProperty WithEnumArrayType(string enumType, int? count = null) + public StructuralMetadataClassProperty WithCount() { - this.Type = ELEMENTTYPE.ENUM; - this.EnumType = enumType; - this.Array = true; - this.Count = count; + Type = ElementType.MAT4; + ComponentType = DataType.FLOAT32; return this; } + + //public StructuralMetadataClassProperty WithValueType(ELEMENTTYPE etype, DATATYPE? ctype = null) + //{ + // Type = etype; + // ComponentType = ctype; + // Array = false; + // return this; + //} + + public StructuralMetadataClassProperty WithArrayType(ELEMENTTYPE etype, DATATYPE? ctype = null, int? count = null) + { + Type = etype; + ComponentType = ctype; + Array = true; + Count = count; + return this; + } + + public StructuralMetadataClassProperty WithEnumArrayType(StructuralMetadataEnum enumeration, int? count = null) + { + Type = ELEMENTTYPE.ENUM; + _enumType = enumeration.LogicalKey; + Array = true; + Count = count; + return this; + } + + public StructuralMetadataClassProperty WithEnumeration(StructuralMetadataEnum enumeration) + { + Type = ELEMENTTYPE.ENUM; + _enumType = enumeration.LogicalKey; + return this; + } + + public StructuralMetadataClassProperty WithRequired(bool required) + { + Required = required; + return this; + } + + public StructuralMetadataClassProperty WithNormalized(bool normalized) + { + Normalized = normalized; + return this; + } + + #endregion } diff --git a/src/SharpGLTF.Ext.3DTiles/Schema2/FeatureIDBuilder.cs b/src/SharpGLTF.Ext.3DTiles/Schema2/FeatureIDBuilder.cs new file mode 100644 index 00000000..54b13027 --- /dev/null +++ b/src/SharpGLTF.Ext.3DTiles/Schema2/FeatureIDBuilder.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using OneOf; + +namespace SharpGLTF.Schema2.Tiles3D +{ + public sealed class FeatureIDBuilder : IMeshFeatureIDInfo, IEquatable + { + public FeatureIDBuilder(int featureCount, OneOf? attributeOrTexture = null, PropertyTable propertyTable = null, IReadOnlyList channels = null, string label = null, int? nullFeatureId = null) + { + Guard.MustBeGreaterThanOrEqualTo(featureCount, 1, nameof(featureCount)); + FeatureCount = featureCount; + + if (attributeOrTexture != null) + { + attributeOrTexture.Value.Switch( + attribute => Attribute = attribute, + texture => + { + Texture = texture; + Channels = channels ?? new[] { 0 }; + } + ); + } + + if (propertyTable != null) + { + PropertyTableIndex = propertyTable.LogicalIndex; + } + + Label = label; + NullFeatureId = nullFeatureId; + } + + public int FeatureCount { get; set; } + public int? NullFeatureId { get; set; } + public int? Attribute { get; set; } + public string Label { get; set; } + + public int? PropertyTableIndex { get; set; } + + public Texture Texture { get; set; } + public IReadOnlyList Channels { get; set; } + + public bool Equals(IMeshFeatureIDInfo other) + { + if (other == null) return false; + if (FeatureCount != other.FeatureCount) return false; + if (NullFeatureId != other.NullFeatureId) return false; + if (Attribute != other.Attribute) return false; + if (Label != other.Label) return false; + if (PropertyTableIndex != other.PropertyTableIndex) return false; + + if (other is FeatureIDBuilder featureIdBuilder) + { + if (Texture != featureIdBuilder.Texture) return false; + if (Channels != featureIdBuilder.Channels) return false; + } + + return true; + } + } +} diff --git a/src/SharpGLTF.Ext.3DTiles/Schema2/IMeshFeatureIDInfo.cs b/src/SharpGLTF.Ext.3DTiles/Schema2/IMeshFeatureIDInfo.cs new file mode 100644 index 00000000..92fb8c38 --- /dev/null +++ b/src/SharpGLTF.Ext.3DTiles/Schema2/IMeshFeatureIDInfo.cs @@ -0,0 +1,38 @@ +namespace SharpGLTF.Schema2.Tiles3D +{ + /// + /// Mesh Feature Ids + /// + /// + /// Implemented by and + /// + public interface IMeshFeatureIDInfo + { + /// + /// The number of unique features in the attribute or texture. + /// + public int FeatureCount { get; set; } + + /// + /// A value that indicates that no feature is associated with this vertex or texel. + /// + public int? NullFeatureId { get; set; } + + /// + /// An attribute containing feature IDs. When `attribute` and `texture` are omitted the + /// feature IDs are assigned to vertices by their index. + /// + public int? Attribute { get; set; } + + /// + /// A label assigned to this feature ID set. Labels must be alphanumeric identifiers + /// matching the regular expression `^[a-zA-Z_][a-zA-Z0-9_]*$`. + /// + public string Label { get; set; } + + /// + /// The index of the property table containing per-feature property values. Only applicable when using the `EXT_structural_metadata` extension. + /// + public int? PropertyTableIndex { get; set; } + } +} diff --git a/src/SharpGLTF.Ext.3DTiles/SharpGLTF.Ext.3DTiles.csproj b/src/SharpGLTF.Ext.3DTiles/SharpGLTF.Ext.3DTiles.csproj index 4b17f977..e2ab93b1 100644 --- a/src/SharpGLTF.Ext.3DTiles/SharpGLTF.Ext.3DTiles.csproj +++ b/src/SharpGLTF.Ext.3DTiles/SharpGLTF.Ext.3DTiles.csproj @@ -20,10 +20,8 @@ - diff --git a/src/SharpGLTF.Ext.3DTiles/cesium_sample_metadata_attributes.png b/src/SharpGLTF.Ext.3DTiles/cesium_sample_metadata_attributes.png new file mode 100644 index 00000000..503fd136 Binary files /dev/null and b/src/SharpGLTF.Ext.3DTiles/cesium_sample_metadata_attributes.png differ diff --git a/src/SharpGLTF.Ext.3DTiles/cesium_sample_metadata_texture.png b/src/SharpGLTF.Ext.3DTiles/cesium_sample_metadata_texture.png new file mode 100644 index 00000000..4292e20d Binary files /dev/null and b/src/SharpGLTF.Ext.3DTiles/cesium_sample_metadata_texture.png differ diff --git a/tests/SharpGLTF.Cesium.Tests/ExtInstanceFeaturesTests.cs b/tests/SharpGLTF.Cesium.Tests/ExtInstanceFeaturesTests.cs index 1ecb3778..e98aa1b4 100644 --- a/tests/SharpGLTF.Cesium.Tests/ExtInstanceFeaturesTests.cs +++ b/tests/SharpGLTF.Cesium.Tests/ExtInstanceFeaturesTests.cs @@ -1,9 +1,9 @@ using NUnit.Framework; using SharpGLTF.Scenes; -using SharpGLTF.Schema2; using SharpGLTF.Transforms; using SharpGLTF.Validation; -using System.Collections.Generic; +using System; +using System.IO; using System.Numerics; using System.Text.Json.Nodes; @@ -18,7 +18,34 @@ public void SetUp() Tiles3DExtensions.RegisterExtensions(); } + // Test files are from https://github.com/CesiumGS/3d-tiles-validator/tree/main/specs/data/gltfExtensions/instanceFeatures + + [Test(Description = "Reads glTF's with EXT_Instance_Features")] + [TestCase(@"InstanceFeaturesFeatureIdAttributeInvalidValue.gltf", typeof(ModelException))] + [TestCase(@"InstanceFeaturesWithoutMeshGpuInstancing.gltf", typeof(SchemaException))] + [TestCase(@"ValidInstanceFeatures.gltf", null)] + public void ReadExtInstanceFeatures(string file, Type exception = null) + { + var fileName = $"./testfixtures/instanceFeatures/{file}"; + + if (exception != null) + { + Assert.Throws(exception, delegate { ModelRoot.Load(fileName); }); + } + else + { + var model = ModelRoot.Load(fileName); + var instanceFeaturesExtension = model.LogicalNodes[0].GetExtension(); + Assert.That(instanceFeaturesExtension.FeatureIds, Is.Not.Null); + Assert.That(instanceFeaturesExtension.FeatureIds, Has.Count.GreaterThanOrEqualTo(1)); + var ctx = new ValidationResult(model, ValidationMode.Strict, true); + model.ValidateContent(ctx.GetContext()); + } + } + + [Test(Description = "Creates a gpu_instancing glTF from a tree with Cesium EXT_Instance_Features")] + // Sample model structure is from https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_instance_features public void AddExtGpuInstanceFeatures() { var settings = SceneBuilderSchema2Settings.WithGpuInstancing; diff --git a/tests/SharpGLTF.Cesium.Tests/ExtMeshFeaturesTests.cs b/tests/SharpGLTF.Cesium.Tests/ExtMeshFeaturesTests.cs index 5c99e6d4..27d6a025 100644 --- a/tests/SharpGLTF.Cesium.Tests/ExtMeshFeaturesTests.cs +++ b/tests/SharpGLTF.Cesium.Tests/ExtMeshFeaturesTests.cs @@ -3,10 +3,10 @@ using SharpGLTF.Geometry.VertexTypes; using SharpGLTF.Materials; using SharpGLTF.Scenes; -using SharpGLTF.Schema2; using SharpGLTF.Validation; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Numerics; @@ -23,13 +23,68 @@ public void SetUp() Tiles3DExtensions.RegisterExtensions(); } + // Test files are from https://github.com/CesiumGS/3d-tiles-validator/tree/main/specs/data/gltfExtensions/meshFeatures + [Test(Description = "Reads glTF's with EXT_Mesh_Features")] + [TestCase(@"ValidFeatureIdAttributeDefault/ValidFeatureIdAttributeDefault.gltf", null)] + [TestCase("FeatureIdAttributeAccessorNormalized.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributeAccessorNotScalar.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributeAttributeInvalidType.gltf", typeof(InvalidOperationException))] + [TestCase("FeatureIdAttributeAttributeInvalidValue.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributeFeatureCountInvalidType.gltf", typeof(InvalidOperationException))] + [TestCase("FeatureIdAttributeFeatureCountInvalidValue.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributeFeatureCountMismatch.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributeFeatureCountMismatchForNullFeatureId.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributeFeatureCountMissing.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributeLabelInvalidType.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributeLabelInvalidValue.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributeNullFeatureIdInvalidType.gltf", typeof(InvalidOperationException))] + [TestCase("FeatureIdAttributeNullFeatureIdInvalidValue.gltf", typeof(ModelException))] + [TestCase("FeatureIdTextureFeatureCountMismatch.gltf", typeof(ModelException))] + [TestCase("FeatureIdTextureSamplerInvalidFilterMode.gltf", typeof(ModelException))] + [TestCase("FeatureIdTextureTextureChannelsInvalidElementType.gltf", typeof(InvalidOperationException))] + [TestCase("FeatureIdTextureTextureChannelsInvalidType.gltf", typeof(SchemaException))] + [TestCase("FeatureIdTextureTextureChannelsTooManyChannels.gltf", typeof(ModelException))] + [TestCase("FeatureIdTextureTextureChannelsTooManyElements.gltf", typeof(ModelException))] + [TestCase("FeatureIdTextureTextureImageDataInvalid.gltf", typeof(ModelException))] + [TestCase("FeatureIdTextureTextureIndexInvalidType.gltf", typeof(InvalidOperationException))] + [TestCase("FeatureIdTextureTextureIndexInvalidValue.gltf", typeof(LinkException))] + [TestCase("FeatureIdTextureTextureInvalidType.gltf", typeof(SchemaException))] + [TestCase("FeatureIdTextureTextureTexCoordInvalidType.gltf", typeof(InvalidOperationException))] + [TestCase("FeatureIdTextureTextureTexCoordInvalidValue.gltf", typeof(ModelException))] + [TestCase("ValidFeatureIdAttribute.gltf", null)] + [TestCase("ValidFeatureIdAttributeWithByteStride.glb", null)] + [TestCase("ValidFeatureIdAttributeWithLargerFeatureCount.gltf", null)] + [TestCase("ValidFeatureIdAttributeWithNullFeatureId.gltf", null)] + [TestCase("ValidFeatureIdTexture.glb", null)] + [TestCase("ValidFeatureIdTexture.gltf", null)] + [TestCase("ValidFeatureIdTextureUsingDefaultChannels.gltf", null)] + public void ReadExtMeshFeaturesFiles(string file, Type exception = null) + { + var fileName = $"./testfixtures/meshFeatures/{file}"; + + if (exception != null) + { + Assert.Throws(exception, delegate { ModelRoot.Load(fileName); }); + } + else + { + var model = ModelRoot.Load(fileName); + var meshFeaturesExtension = model.LogicalMeshes[0].Primitives[0].GetExtension(); + Assert.That(meshFeaturesExtension.FeatureIds, Is.Not.Null); + Assert.That(meshFeaturesExtension.FeatureIds, Has.Count.GreaterThanOrEqualTo(1)); + var ctx = new ValidationResult(model, ValidationMode.Strict, true); + model.ValidateContent(ctx.GetContext()); + } + } + [Test(Description = "Test for settting the FeatureIds with vertex attributes. See sample https://github.com/CesiumGS/3d-tiles-samples/blob/main/glTF/EXT_mesh_features/FeatureIdAttribute")] + // In the sample html code, there is a shader that uses the feature ID to color the triangle public void FeaturesIdAttributeTest() { TestContext.CurrentContext.AttachGltfValidatorLinks(); // Create a triangle with feature ID custom vertex attribute - var featureId = 1; + var featureId = 2; var material = MaterialBuilder.CreateDefault().WithDoubleSide(true); var mesh = new MeshBuilder("mesh"); @@ -46,17 +101,15 @@ public void FeaturesIdAttributeTest() var model = scene.ToGltf2(); // Set the FeatureIds - var featureIdAttribute = new FeatureIDBuilder(1, 0); - model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds((featureIdAttribute,null,null)); + var featureIdAttribute = new FeatureIDBuilder(1, 0); + model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds(featureIdAttribute); // Validate the FeatureIds - var cesiumExtMeshFeaturesExtension = (MeshExtMeshFeatures)model.LogicalMeshes[0].Primitives[0].Extensions.FirstOrDefault(); - Assert.That(cesiumExtMeshFeaturesExtension.FeatureIds, Is.Not.Null); - - // Assert.That(cesiumExtMeshFeaturesExtension.FeatureIds[0], Is.EqualTo(featureIdAttribute)); // this cannot be run anymore + var meshFeaturesExtension = (MeshExtMeshFeatures)model.LogicalMeshes[0].Primitives[0].Extensions.FirstOrDefault(); + Assert.That(meshFeaturesExtension.FeatureIds, Is.Not.Null); // Check there should be a custom vertex attribute with name _FEATURE_ID_{attribute} - var attribute = cesiumExtMeshFeaturesExtension.FeatureIds[0].Attribute; + var attribute = meshFeaturesExtension.FeatureIds[0].Attribute; Assert.That(attribute == 0); var primitive = model.LogicalMeshes[0].Primitives[0]; var featureIdVertexAccessor = primitive.GetVertexAccessor($"_FEATURE_ID_{attribute}"); @@ -73,6 +126,7 @@ public void FeaturesIdAttributeTest() } [Test(Description = "Test for settting the FeatureIds with a texture. See sample https://github.com/CesiumGS/3d-tiles-samples/blob/main/glTF/EXT_mesh_features/FeatureIdTexture")] + // In the sample html code, there is a shader that uses the feature'ID from the texture to color the 2 triangles public void FeaturesIdTextureTest() { TestContext.CurrentContext.AttachGltfValidatorLinks(); @@ -107,21 +161,20 @@ public void FeaturesIdTextureTest() var model = scene.ToGltf2(); // Set the FeatureIds, pointing to the red channel of the texture - var featureId = new FeatureIDBuilder(4); + var featureId = new FeatureIDBuilder(4, model.LogicalTextures[0]); var primitive = model.LogicalMeshes[0].Primitives[0]; - primitive.AddMeshFeatureIds((featureId, model.LogicalTextures[0], new int[] { 0 })); - - var cesiumExtMeshFeaturesExtension = (MeshExtMeshFeatures)primitive.Extensions.FirstOrDefault(); - Assert.That(cesiumExtMeshFeaturesExtension.FeatureIds, Is.Not.Null); + primitive.AddMeshFeatureIds(featureId); - // Assert.That(cesiumExtMeshFeaturesExtension.FeatureIds, Is.EqualTo(featureIds)); - // var featureId = cesiumExtMeshFeaturesExtension.FeatureIds[0]; - // var texCoord = featureId.Texture.TextureCoordinate; + var meshFeaturesExtension = (MeshExtMeshFeatures)primitive.Extensions.FirstOrDefault(); + Assert.That(meshFeaturesExtension.FeatureIds, Is.Not.Null); - // var textureIdVertexAccessor = primitive.GetVertexAccessor($"TEXCOORD_{texCoord}"); - // Assert.That(textureIdVertexAccessor, Is.Not.Null); - // Assert.That(textureIdVertexAccessor.AsVector2Array(), Has.Count.EqualTo(4)); + var firstFeatureId = meshFeaturesExtension.FeatureIds[0]; + var texture = firstFeatureId.GetTexture(); + var texCoord = texture.TextureCoordinate; + var textureIdVertexAccessor = primitive.GetVertexAccessor($"TEXCOORD_{texCoord}"); + Assert.That(textureIdVertexAccessor, Is.Not.Null); + Assert.That(textureIdVertexAccessor.AsVector2Array(), Has.Count.EqualTo(4)); var ctx = new ValidationResult(model, ValidationMode.Strict, true); @@ -130,6 +183,5 @@ public void FeaturesIdTextureTest() scene.AttachToCurrentTest("cesium_ext_mesh_features_feature_id_texture.gltf"); scene.AttachToCurrentTest("cesium_ext_mesh_features_feature_id_texture.plotly"); } - } } diff --git a/tests/SharpGLTF.Cesium.Tests/ExtPrimitiveOutlineTests.cs b/tests/SharpGLTF.Cesium.Tests/ExtPrimitiveOutlineTests.cs index dd6b3874..b2a49347 100644 --- a/tests/SharpGLTF.Cesium.Tests/ExtPrimitiveOutlineTests.cs +++ b/tests/SharpGLTF.Cesium.Tests/ExtPrimitiveOutlineTests.cs @@ -1,7 +1,6 @@ using System.Linq; using System.Numerics; using NUnit.Framework; -using SharpGLTF.Schema2; using SharpGLTF.Geometry; using SharpGLTF.Geometry.VertexTypes; using SharpGLTF.Materials; diff --git a/tests/SharpGLTF.Cesium.Tests/ExtStructuralMetadataTests.cs b/tests/SharpGLTF.Cesium.Tests/ExtStructuralMetadataTests.cs index 43062653..0efb98ff 100644 --- a/tests/SharpGLTF.Cesium.Tests/ExtStructuralMetadataTests.cs +++ b/tests/SharpGLTF.Cesium.Tests/ExtStructuralMetadataTests.cs @@ -3,10 +3,10 @@ using SharpGLTF.Geometry.VertexTypes; using SharpGLTF.Materials; using SharpGLTF.Scenes; -using SharpGLTF.Schema2; using SharpGLTF.Validation; using System; using System.Collections.Generic; +using System.Linq; using System.Numerics; namespace SharpGLTF.Schema2.Tiles3D @@ -22,53 +22,307 @@ public void SetUp() Tiles3DExtensions.RegisterExtensions(); } - /* + // Test files are from https://github.com/CesiumGS/3d-tiles-validator/tree/main/specs/data/gltfExtensions/structuralMetadata + [Test(Description = "Reads glTF's with EXT_Structural_Metadata")] + [TestCase("ExtensionInMeshPrimitiveWithoutTopLevelObject.gltf", typeof(ModelException))] + [TestCase("PropertyAttributesClassPropertyArray.gltf", typeof(ModelException))] + [TestCase("PropertyAttributesClassPropertyInvalidComponentType.gltf", typeof(ModelException))] + [TestCase("PropertyAttributesClassPropertyInvalidEnumValueType.gltf", typeof(ModelException))] + // Todo: Minmax [TestCase("PropertyAttributesClassPropertyMaxNotInRange.gltf", typeof(ModelException))] + // Todo: Minmax [TestCase("PropertyAttributesClassPropertyMinNotInRange.gltf", typeof(ModelException))] + [TestCase("PropertyAttributesClassPropertyString.gltf", typeof(ModelException))] + [TestCase("PropertyAttributesMeshPrimitivePropertyAttributesInvalidElementType.gltf", typeof(InvalidOperationException))] + [TestCase("PropertyAttributesMeshPrimitivePropertyAttributesInvalidElementValue.gltf", typeof(LinkException))] + [TestCase("PropertyAttributesMeshPrimitivePropertyAttributesInvalidLength.gltf", typeof(SchemaException))] + [TestCase("PropertyAttributesMeshPrimitivePropertyAttributesInvalidType.gltf", typeof(SchemaException))] + [TestCase("PropertyAttributesPropertyAttributePropertyInvalidAttribute.gltf", typeof(ModelException))] + // Todo: Minmax [TestCase("PropertyAttributesPropertyAttributePropertyMaxMismatch.gltf", typeof(ModelException))] + // Todo: Minmax [TestCase("PropertyAttributesPropertyAttributePropertyMaxNotInRange.gltf", typeof(ModelException))] + // Todo: Minmax [TestCase("PropertyAttributesPropertyAttributePropertyMinMismatch.gltf", typeof(ModelException))] + // Todo: Minmax [TestCase("PropertyAttributesPropertyAttributePropertyMinNotInRange.gltf", typeof(ModelException))] + // todo minmax with texture [TestCase("PropertyTextureClassPropertyMaxNotInRange.gltf", typeof(ModelException))] + // todo minmax with texture [TestCase("PropertyTextureClassPropertyMinNotInRange.gltf", typeof(ModelException))] + // todo minmax with texture [TestCase("PropertyTextureClassPropertyWithOffsetScaleMinNotInRange.gltf", typeof(ModelException))] + // todo minmax with texture [TestCase("PropertyTextureEnumsInvalidEnumValue.gltf", typeof(ModelException))] + [TestCase("PropertyTextureInvalidPropertyTypeA.gltf", typeof(ModelException))] + [TestCase("PropertyTextureInvalidPropertyTypeB.gltf", typeof(ModelException))] + [TestCase("PropertyTextureMeshPrimitivePropertyTexturesInvalidElementType.gltf", typeof(InvalidOperationException))] + [TestCase("PropertyTextureMeshPrimitivePropertyTexturesInvalidElementValue.gltf", typeof(LinkException))] + [TestCase("PropertyTextureMeshPrimitivePropertyTexturesInvalidLength.gltf", typeof(SchemaException))] + [TestCase("PropertyTextureMeshPrimitivePropertyTexturesInvalidType.gltf", typeof(SchemaException))] + [TestCase("PropertyTextureMeshPrimitivePropertyTextureTexCoordInvalidValue.gltf", typeof(ModelException))] + [TestCase("PropertyTexturePropertyChannelsSizeMismatch.gltf", typeof(ModelException))] + [TestCase("PropertyTexturePropertyIndexInvalidType.gltf", typeof(InvalidOperationException))] + [TestCase("PropertyTexturePropertyIndexInvalidValue.gltf", typeof(LinkException))] + // todo minmax with texture [TestCase("PropertyTexturePropertyTexturePropertyMaxMismatch.gltf", typeof(ModelException))] + // todo minmax with texture [TestCase("PropertyTexturePropertyTexturePropertyMaxNotInRange.gltf", typeof(ModelException))] + // todo minmax with texture [TestCase("PropertyTexturePropertyTexturePropertyMinMismatch.gltf", typeof(ModelException))] + // todo minmax with texture[TestCase("PropertyTexturePropertyTexturePropertyMinNotInRange.gltf", typeof(ModelException))] + [TestCase("StructuralMetadataMissingSchema.gltf", typeof(ModelException))] + [TestCase("StructuralMetadataSchemaAndSchemaUri.gltf", typeof(ModelException))] + [TestCase("ValidMultipleClasses.gltf", null)] + [TestCase("ValidPropertyAttributes.gltf", null)] + [TestCase("ValidPropertyTexture.gltf", null)] + [TestCase("ValidPropertyTextureEnums.gltf", null)] + + public void ReadExtStructuralMetadata(string file, Type exception = null) + { + var fileName = $"./testfixtures/structuralMetadata/{file}"; + + if (exception != null) + { + Assert.Throws(exception, delegate { ModelRoot.Load(fileName); }); + } + else + { + var model = ModelRoot.Load(fileName); + var structuralMetadataExtension = model.GetExtension(); + var ctx = new ValidationResult(model, ValidationMode.Strict, true); + model.ValidateContent(ctx.GetContext()); + } + } + + + [Test(Description = "MinimalMetadataAttributeSample")] + public void MinimalMetadataAttributeSample() + { + TestContext.CurrentContext.AttachGltfValidatorLinks(); + + int featureId = 0; + var material = MaterialBuilder.CreateDefault().WithDoubleSide(true); + + var mesh = new MeshBuilder("mesh"); + var prim = mesh.UsePrimitive(material); + + var vt0 = VertexBuilder.GetVertexWithFeatureId(new Vector3(0, 0, 0), new Vector3(0, 0, 1), featureId); + var vt1 = VertexBuilder.GetVertexWithFeatureId(new Vector3(1, 0, 0), new Vector3(0, 0, 1), featureId); + var vt2 = VertexBuilder.GetVertexWithFeatureId(new Vector3(0, 1, 0), new Vector3(0, 0, 1), featureId); + + prim.AddTriangle(vt0, vt1, vt2); + var scene = new SceneBuilder(); + scene.AddRigidMesh(mesh, Matrix4x4.Identity); + var model = scene.ToGltf2(); + + var rootMetadata = model.UseStructuralMetadata(); + var schema = rootMetadata.UseEmbeddedSchema("schema_001"); + + var schemaClass = schema.UseClassMetadata("triangles"); + + var nameProperty = schemaClass + .UseProperty("name") + .WithStringType(); + + var propertyTable = schemaClass.AddPropertyTable(1); + + propertyTable + .UseProperty(nameProperty) + .SetValues("this is featureId0"); + + foreach (var primitive in model.LogicalMeshes[0].Primitives) + { + var featureIdAttribute = new FeatureIDBuilder(1, 0, propertyTable); + primitive.AddMeshFeatureIds(featureIdAttribute); + } + + // create files + var ctx = new ValidationResult(model, ValidationMode.Strict, true); + model.AttachToCurrentTest("cesium_ext_structural_minimal_metadata_sample.glb"); + model.AttachToCurrentTest("cesium_ext_structural_minimal_metadata_sample.gltf"); + model.AttachToCurrentTest("cesium_ext_structural_minimal_metadata_sample.plotly"); + } + + + [Test(Description = "TestWith2PrimitivesAndMetadata")] + public void MultiplePrimitivesAndMetadata() + { + TestContext.CurrentContext.AttachGltfValidatorLinks(); + + int featureId = 0; + var material = MaterialBuilder.CreateDefault().WithDoubleSide(true); + + var mesh = new MeshBuilder("mesh"); + var prim = mesh.UsePrimitive(material); + + var vt0 = VertexBuilder.GetVertexWithFeatureId(new Vector3(0, 0, 0), new Vector3(0, 0, 1), featureId); + var vt1 = VertexBuilder.GetVertexWithFeatureId(new Vector3(1, 0, 0), new Vector3(0, 0, 1), featureId); + var vt2 = VertexBuilder.GetVertexWithFeatureId(new Vector3(0, 1, 0), new Vector3(0, 0, 1), featureId); + + prim.AddTriangle(vt0, vt1, vt2); + + // featureId = 1 and 2 (other material) + + var material2 = new MaterialBuilder() + .WithDoubleSide(true) + .WithMetallicRoughnessShader() + .WithChannelParam(KnownChannel.BaseColor, KnownProperty.RGBA, new Vector4(1, 0, 1, 1)); + + var prim2 = mesh.UsePrimitive(material2); + + featureId = 1; + var vt3 = VertexBuilder.GetVertexWithFeatureId(new Vector3(2, 0, 0), new Vector3(0, 0, 1), featureId); + var vt4 = VertexBuilder.GetVertexWithFeatureId(new Vector3(3, 0, 0), new Vector3(0, 0, 1), featureId); + var vt5 = VertexBuilder.GetVertexWithFeatureId(new Vector3(2, 1, 0), new Vector3(0, 0, 1), featureId); + + prim2.AddTriangle(vt3, vt4, vt5); + + featureId = 2; + var vt6 = VertexBuilder.GetVertexWithFeatureId(new Vector3(4, 0, 0), new Vector3(0, 0, 1), featureId); + var vt7 = VertexBuilder.GetVertexWithFeatureId(new Vector3(5, 0, 0), new Vector3(0, 0, 1), featureId); + var vt8 = VertexBuilder.GetVertexWithFeatureId(new Vector3(4, 1, 0), new Vector3(0, 0, 1), featureId); + + prim2.AddTriangle(vt6, vt7, vt8); + + var scene = new SceneBuilder(); + scene.AddRigidMesh(mesh, Matrix4x4.Identity); + var model = scene.ToGltf2(); + + var rootMetadata = model.UseStructuralMetadata(); + var schema = rootMetadata.UseEmbeddedSchema("schema_001"); + schema.Name = "schema 001"; + schema.Description = "an example schema"; + schema.Version = "3.5.1"; + + var trianglesClass = schema + .UseClassMetadata("triangles") + .WithName("Triangle"); + + var nameProperty = trianglesClass + .UseProperty("name") + .WithStringType(); + + + var isTriangle = trianglesClass + .UseProperty("IsTriangle") + .WithBooleanType(); + + var propertyTable = trianglesClass + .AddPropertyTable(3, "PropertyTable"); + + propertyTable + .UseProperty(nameProperty) + .SetValues("this is featureId0", "this is featureId1", "this is featureId2"); + + propertyTable + .UseProperty(isTriangle) + .SetValues(false, true, false); + + + foreach (var primitive in model.LogicalMeshes[0].Primitives) + { + var triangles = primitive.EvaluateTriangles().Count(); + var featureIdAttribute = new FeatureIDBuilder(triangles, 0, propertyTable); + primitive.AddMeshFeatureIds(featureIdAttribute); + } + + // create files + var ctx = new ValidationResult(model, ValidationMode.Strict, true); + model.AttachToCurrentTest("cesium_ext_structural_metadata_multiple_primitives.glb"); + model.AttachToCurrentTest("cesium_ext_structural_metadata_multiple_primitives.gltf"); + model.AttachToCurrentTest("cesium_ext_structural_metadata_multiple_primitives.plotly"); + } + + [Test(Description = "First test with ext_structural_metadata")] + // This test creates a simple triangle (featureId = 0) with ext_structural_metadata (4 tree attributes like + // species (Enumeration), age (Scalar), height (Scalar) and diameter (Scalar) and a property table. + // following the structure described in https://github.com/CesiumGS/glTF/tree/proposal-EXT_structural_metadata/extensions/2.0/Vendor/EXT_structural_metadata public void TriangleWithMetadataTest() { TestContext.CurrentContext.AttachGltfValidatorLinks(); var material = MaterialBuilder.CreateDefault().WithDoubleSide(true); - var mesh = new MeshBuilder("mesh"); + + var mesh = new MeshBuilder("mesh"); var prim = mesh.UsePrimitive(material); - prim.AddTriangle(new VertexPosition(-10, 0, 0), new VertexPosition(10, 0, 0), new VertexPosition(0, 10, 0)); + var features = new List() { 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(); - - var schema = new StructuralMetadataSchema(); - schema.Id = "schema_001"; + + var rootMetadata = model.UseStructuralMetadata(); + var schema = rootMetadata.UseEmbeddedSchema("schema_001"); schema.Name = "schema 001"; schema.Description = "an example schema"; schema.Version = "3.5.1"; - var classes = new Dictionary(); - var treeClass = new StructuralMetadataClass(); - treeClass.Name = "Tree"; - treeClass.Description = "Woody, perennial plant."; - classes["tree"] = treeClass; - var ageProperty = new ClassProperty(); - ageProperty.Description = "The age of the tree, in years"; - ageProperty.Type = ElementType.SCALAR; - ageProperty.ComponentType = DataType.UINT32; - ageProperty.Required = true; - treeClass.Properties.Add("age", ageProperty); + var speciesEnum = schema.UseEnumMetadata("speciesEnum", ("Unspecified", 0), ("Oak", 1), ("Pine", 2), ("Maple",3)); + speciesEnum.Name = "Species"; + speciesEnum.Description = "An example enum for tree species."; + + var treeClass = schema + .UseClassMetadata("tree") + .WithName("Tree") + .WithDescription("Woody, perennial plant."); + + // species property + var speciesProperty = treeClass + .UseProperty("species") + .WithDescription("Type of tree.") + .WithEnumeration(speciesEnum) + .WithRequired(true); + + // age property + var ageProperty = treeClass + .UseProperty("age") + .WithDescription("The age of the tree, in years") + .WithUInt32Type() + .WithRequired(true); + + // Height property + var heightProperty = treeClass + .UseProperty("height") + .WithDescription("Height of tree measured from ground level, in meters"); + heightProperty.WithFloat32Type(); + + // Diameter property + var diameterProperty = treeClass + .UseProperty("diameter") + .WithDescription("Diameter at trunk base, in meters."); + diameterProperty.WithFloat32Type(); + + var propertyTable = treeClass + .AddPropertyTable(features.Count, "PropertyTable"); + + propertyTable + .UseProperty(ageProperty) + .SetValues((uint)100, (uint)101); + + propertyTable + .UseProperty(speciesProperty) + .SetValues((short)0, (short)3); - schema.Classes = classes; + propertyTable.UseProperty(heightProperty) + .SetValues(10.0f, 11f); - var propertyTable = new PropertyTable("tree", 1, "PropertyTable"); - var agePropertyTableProperty = model.GetPropertyTableProperty(new List() { 100 }); - propertyTable.Properties.Add("age", agePropertyTableProperty); + propertyTable.UseProperty(diameterProperty) + .SetValues(1.5f, 2f); - model.SetPropertyTable(propertyTable, schema); + // Set the FeatureIds + var cnt = propertyTable.Count; + var featureIdAttribute = new FeatureIDBuilder(2, 0, propertyTable); + 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"); - }*/ + } + [Test(Description = "ext_structural_metadata with FeatureId Texture and Property Table")] // sample see https://github.com/CesiumGS/3d-tiles-samples/tree/main/glTF/EXT_structural_metadata/FeatureIdTextureAndPropertyTable @@ -109,8 +363,6 @@ public void FeatureIdTextureAndPropertytableTest() scene.AddRigidMesh(mesh, Matrix4x4.Identity); var model = scene.ToGltf2(); - // -------------------------------------------------------------- - var rootMetadata = model.UseStructuralMetadata(); var schema = rootMetadata.UseEmbeddedSchema("FeatureIdTextureAndPropertyTableSchema"); @@ -118,38 +370,38 @@ public void FeatureIdTextureAndPropertytableTest() var buildingComponentsClass = schema .UseClassMetadata("buildingComponents") - .WithNameAndDesc("Building components"); + .WithName("Building components") + .WithDescription("The components of a building."); var componentProp = buildingComponentsClass .UseProperty("component") - .WithNameAndDesc("Component") - .WithValueType(ElementType.STRING); + .WithName("Component") + .WithStringType(); var yearProp = buildingComponentsClass .UseProperty("yearBuilt") - .WithNameAndDesc("Year built") - .WithValueType(ElementType.SCALAR, DataType.INT16); + .WithName("Year built") + .WithInt16Type(); var propertyTable = buildingComponentsClass .AddPropertyTable(4, "Example property table"); propertyTable .UseProperty(componentProp) - .SetValues1D("Wall", "Door", "Roof", "Window"); + .SetValues("Wall", "Door", "Roof", "Window"); propertyTable .UseProperty(yearProp) - .SetValues1D(1960, 1996, 1985, 2002); + .SetValues((short)1960, (short)1996, (short)1985, (short)2002); // Set the FeatureIds, pointing to the red channel of the texture - var featureId = new FeatureIDBuilder(propertyTable); + var featureId = new FeatureIDBuilder(4, null, propertyTable); var primitive = model.LogicalMeshes[0].Primitives[0]; - primitive.AddMeshFeatureIds((featureId, model.LogicalTextures[0], new[] {0})); + 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"); @@ -204,22 +456,23 @@ public void SimplePropertyTextureTest() var exampleMetadataClass = schema .UseClassMetadata("buildingComponents") - .WithNameAndDesc("Building properties"); + .WithName("Building properties"); exampleMetadataClass .UseProperty("insideTemperature") - .WithNameAndDesc("Inside temperature") - .WithValueType(ElementType.SCALAR, DataType.UINT8); + .WithName("Inside temperature") + .WithUInt8Type(); exampleMetadataClass .UseProperty("outsideTemperature") - .WithNameAndDesc("Outside temperature") - .WithValueType(ElementType.SCALAR, DataType.UINT8); + .WithName("Outside temperature") + .WithUInt8Type(); exampleMetadataClass .UseProperty("insulation") - .WithNameAndDesc("Insulation Thickness") - .WithValueType(ElementType.SCALAR, DataType.UINT8, true); + .WithName("Insulation Thickness") + .WithUInt8Type() + .WithNormalized(true); // define texture property @@ -232,7 +485,7 @@ public void SimplePropertyTextureTest() // assign to primitive var primitive = model.LogicalMeshes[0].Primitives[0]; - primitive.AddPropertyTexture(buildingPropertyTexture); + primitive.AddPropertyTexture(buildingPropertyTexture); var ctx = new ValidationResult(model, ValidationMode.Strict, true); model.AttachToCurrentTest("cesium_ext_structural_metadata_simple_property_texture.glb"); @@ -276,17 +529,20 @@ public void MultipleFeatureIdsAndPropertiesTest() var exampleMetadataClass = schema .UseClassMetadata("exampleMetadataClass") - .WithNameAndDesc("Example metadata class", "An example metadata class"); + .WithName("Example metadata class") + .WithDescription("An example metadata class"); var vec3Property = exampleMetadataClass .UseProperty("example_VEC3_FLOAT32") - .WithNameAndDesc("Example VEC3 FLOAT32 property", "An example property, with type VEC3, with component type FLOAT32") - .WithValueType(ElementType.VEC3, DataType.FLOAT32); + .WithName("Example VEC3 FLOAT32 property") + .WithDescription("An example property, with type VEC3, with component type FLOAT32") + .WithVector3Type(); var stringProperty = exampleMetadataClass .UseProperty("example_STRING") - .WithNameAndDesc("Example STRING property", "An example property, with type STRING") - .WithValueType(ElementType.STRING); + .WithName("Example STRING property") + .WithDescription("An example property, with type STRING") + .WithStringType(); // define table @@ -294,18 +550,18 @@ public void MultipleFeatureIdsAndPropertiesTest() examplePropertyTable .UseProperty(vec3Property) - .SetValues1D(new Vector3(3, 3.0999999046325684f, 3.200000047683716f), new Vector3(103, 103.0999999046325684f, 103.200000047683716f)); + .SetValues(new Vector3(3, 3.0999999046325684f, 3.200000047683716f), new Vector3(103, 103.0999999046325684f, 103.200000047683716f)); examplePropertyTable .UseProperty(stringProperty) - .SetValues1D("Rain 🌧", "Thunder ⛈"); + .SetValues("Rain 🌧", "Thunder ⛈"); // assign to primitive - var featureId0 = new FeatureIDBuilder(examplePropertyTable, 0); - var featureId1 = new FeatureIDBuilder(examplePropertyTable, 1); + var featureId0 = new FeatureIDBuilder(2, 0, examplePropertyTable); + var featureId1 = new FeatureIDBuilder(2, 1, examplePropertyTable); - model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds( (featureId0, null, null), (featureId1, null, null) ); + model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds( featureId0, featureId1 ); var ctx = new ValidationResult(model, ValidationMode.Strict, true); model.AttachToCurrentTest("cesium_ext_structural_metadata_featureid_attribute_and_property_table.glb"); @@ -343,17 +599,20 @@ public void FeatureIdAndPropertyTableTest() var exampleMetadataClass = schema .UseClassMetadata("exampleMetadataClass") - .WithNameAndDesc("Example metadata class", "An example metadata class"); + .WithName("Example metadata class") + .WithDescription("An example metadata class"); var vector3Property = exampleMetadataClass .UseProperty("example_VEC3_FLOAT32") - .WithNameAndDesc("Example VEC3 FLOAT32 property", "An example property, with type VEC3, with component type FLOAT32") - .WithValueType(ElementType.VEC3, DataType.FLOAT32); + .WithName("Example VEC3 FLOAT32 property") + .WithDescription("An example property, with type VEC3, with component type FLOAT32") + .WithVector3Type(); var matrix4x4Property = exampleMetadataClass .UseProperty("example_MAT4_FLOAT32") - .WithNameAndDesc("Example MAT4 FLOAT32 property", "An example property, with type MAT4, with component type FLOAT32") - .WithValueType(ElementType.MAT4, DataType.FLOAT32); + .WithName("Example MAT4 FLOAT32 property") + .WithDescription("An example property, with type MAT4, with component type FLOAT32") + .WithMatrix4x4Type(); // define table @@ -361,17 +620,17 @@ public void FeatureIdAndPropertyTableTest() examplePropertyTable .UseProperty(vector3Property) - .SetValues1D(new Vector3(3, 3.0999999046325684f, 3.200000047683716f)); + .SetValues(new Vector3(3, 3.0999999046325684f, 3.200000047683716f)); examplePropertyTable .UseProperty(matrix4x4Property) - .SetValues1D(Matrix4x4.Identity); + .SetValues(Matrix4x4.Identity); // assign to primitive - var featureId = new FeatureIDBuilder(examplePropertyTable, 0); + var featureId = new FeatureIDBuilder(1, 0, examplePropertyTable); - model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds((featureId, null, null)); + model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds(featureId); var ctx = new ValidationResult(model, ValidationMode.Strict, true); model.AttachToCurrentTest("cesium_ext_structural_metadata_multiple_featureids_and_properties.glb"); @@ -409,61 +668,72 @@ public void ComplexTypesTest() var exampleMetadataClass = schema .UseClassMetadata("exampleMetadataClass") - .WithNameAndDesc("Example metadata class A", "First example metadata class"); + .WithName("Example metadata class A") + .WithDescription("First example metadata class"); // enums var exampleEnum = schema.UseEnumMetadata("exampleEnumType", ("ExampleEnumValueA", 0), ("ExampleEnumValueB", 1), ("ExampleEnumValueC", 2)); - // class properties + //// class properties var uint8ArrayProperty = exampleMetadataClass .UseProperty("example_variable_length_ARRAY_normalized_UINT8") - .WithNameAndDesc("Example variable-length ARRAY normalized INT8 property","An example property, with type ARRAY, with component type UINT8, normalized, and variable length") - .WithArrayType(ElementType.SCALAR,DataType.UINT8,false); + .WithName("Example variable-length ARRAY normalized INT8 property") + .WithDescription("An example property, with type ARRAY, with component type UINT8, normalized, and variable length") + .WithArrayType(ElementType.SCALAR, DataType.UINT8) + .WithNormalized(false); var fixedLengthBooleanProperty = exampleMetadataClass .UseProperty("example_fixed_length_ARRAY_BOOLEAN") - .WithNameAndDesc("Example fixed-length ARRAY BOOLEAN property", "An example property, with type ARRAY, with component type BOOLEAN, and fixed length ") - .WithArrayType(ElementType.BOOLEAN, null, false, 4); + .WithName("Example fixed-length ARRAY BOOLEAN property") + .WithDescription("An example property, with type ARRAY, with component type BOOLEAN, and fixed length ") + .WithArrayType(ElementType.BOOLEAN, null, 4) + .WithNormalized(false); var variableLengthStringArrayProperty = exampleMetadataClass .UseProperty("example_variable_length_ARRAY_STRING") - .WithNameAndDesc("Example variable-length ARRAY STRING property", "An example property, with type ARRAY, with component type STRING, and variable length") + .WithName("Example variable-length ARRAY STRING property") + .WithDescription("An example property, with type ARRAY, with component type STRING, and variable length") .WithArrayType(ElementType.STRING); var fixed_length_ARRAY_ENUM = exampleMetadataClass .UseProperty("example_fixed_length_ARRAY_ENUM") - .WithNameAndDesc("Example fixed-length ARRAY ENUM property", "An example property, with type ARRAY, with component type ENUM, and fixed length") + .WithName("Example fixed-length ARRAY ENUM property") + .WithDescription("An example property, with type ARRAY, with component type ENUM, and fixed length") .WithEnumArrayType(exampleEnum, 2); - // property tables - var examplePropertyTable = exampleMetadataClass.AddPropertyTable(1, "Example property table"); - // Question: The table declares a feature count of 1, but then, these properties define different number of items - + var bytes = new List>(); + bytes.Add(new List() { 0, 1, 2, 3, 4, 5, 6, 7 }); examplePropertyTable .UseProperty(uint8ArrayProperty) - .SetValues1D(0, 1, 2, 3, 4, 5, 6, 7); + .SetArrayValues(bytes); + var bools = new List>(); + bools.Add(new List() { true, false, true, false }); examplePropertyTable .UseProperty(fixedLengthBooleanProperty) - .SetValues1D(true, false, true, false); + .SetArrayValues(bools); + var strings = new List>(); + strings.Add(["Example string 1", "Example string 2", "Example string 3"]); examplePropertyTable .UseProperty(variableLengthStringArrayProperty) - .SetValues1D("Example string 1", "Example string 2", "Example string 3"); + .SetArrayValues(strings); + // Fill property table with enum values + var shorts = new List>(); + shorts.Add([0, 1]); examplePropertyTable .UseProperty(fixed_length_ARRAY_ENUM) - .SetValues1D(0, 1); + .SetArrayValues(shorts); // add to primitive + var featureId = new FeatureIDBuilder(1, 0, examplePropertyTable); - var featureId = new FeatureIDBuilder(examplePropertyTable, 0); - - model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds((featureId, null, null)); + model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds(featureId); var ctx = new ValidationResult(model, ValidationMode.Strict, true); model.AttachToCurrentTest("cesium_ext_structural_metadata_complex_types.glb"); @@ -490,8 +760,6 @@ public void MultipleClassesTest() scene.AddRigidMesh(mesh, Matrix4x4.Identity); var model = scene.ToGltf2(); - // -------------------------------------------------------------- - var rootMetadata = model.UseStructuralMetadata(); var schema = rootMetadata.UseEmbeddedSchema("MultipleClassesSchema"); @@ -499,46 +767,51 @@ public void MultipleClassesTest() var classA = schema .UseClassMetadata("exampleMetadataClassA") - .WithNameAndDesc("Example metadata class A","First example metadata class"); + .WithName("Example metadata class A") + .WithDescription("First example metadata class"); var classAp0 = classA.UseProperty("example_FLOAT32") - .WithNameAndDesc("Example FLOAT32 property", "An example property, with component type FLOAT32") - .WithValueType(ElementType.SCALAR, DataType.FLOAT32); + .WithName("Example FLOAT32 property") + .WithDescription("An example property, with component type FLOAT32") + .WithFloat32Type(); var classAp1 = classA.UseProperty("example_INT64") - .WithNameAndDesc("Example INT64 property", "An example property, with component type INT64") - .WithValueType(ElementType.SCALAR, DataType.INT64); + .WithName("Example INT64 property") + .WithDescription("An example property, with component type INT64") + .WithInt64Type(); var classB = schema.UseClassMetadata("exampleMetadataClassB") - .WithNameAndDesc("Example metadata class B", "Second example metadata class"); + .WithName("Example metadata class B") + .WithDescription("Second example metadata class"); var classBp0 = classB.UseProperty("example_UINT16") - .WithNameAndDesc("Example UINT16 property", "An example property, with component type UINT16") - .WithValueType(ElementType.SCALAR, DataType.UINT16); + .WithName("Example UINT16 property") + .WithDescription("An example property, with component type UINT16") + .WithUInt16Type(); var classBp1 = classB.UseProperty("example_FLOAT64") - .WithNameAndDesc("Example FLOAT64 property", "An example property, with component type FLOAT64") - .WithValueType(ElementType.SCALAR, DataType.FLOAT64); + .WithName("Example FLOAT64 property") + .WithDescription("An example property, with component type FLOAT64") + .WithFloat64Type(); // properties var firstPropertyTable = classA.AddPropertyTable(1, "First example property table"); - firstPropertyTable.UseProperty(classAp0).SetValues1D(100); - firstPropertyTable.UseProperty(classAp1).SetValues1D(101); + firstPropertyTable.UseProperty(classAp0).SetValues(100); + firstPropertyTable.UseProperty(classAp1).SetValues(101); var secondPropertyTable = classB.AddPropertyTable(1, "Second example property table"); - secondPropertyTable.UseProperty(classBp0).SetValues1D(102); - secondPropertyTable.UseProperty(classBp1).SetValues1D(103); + secondPropertyTable.UseProperty(classBp0).SetValues(102); + secondPropertyTable.UseProperty(classBp1).SetValues(103); // features - // FeatureID 0: featureCount=1, attribute=0, porpertyTable=0 - var featureId0 = new FeatureIDBuilder(firstPropertyTable, 0); - // FeatureID 1: featureCount=1, attribute=1, porpertyTable=1 - var featureId1 = new FeatureIDBuilder(secondPropertyTable, 1); + // FeatureID 0: featureCount=1, attribute=0, propertyTable=0 + var featureId0 = new FeatureIDBuilder(1, 0, firstPropertyTable); + // FeatureID 1: featureCount=1, attribute=1, prorpertyTable=1 + var featureId1 = new FeatureIDBuilder(1, 1, secondPropertyTable); - model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds((featureId0, null,null), (featureId1,null,null)); - + model.LogicalMeshes[0].Primitives[0].AddMeshFeatureIds(featureId0, featureId1); var ctx = new ValidationResult(model, ValidationMode.Strict, true); model.AttachToCurrentTest("cesium_ext_structural_metadata_multiple_classes.glb"); model.AttachToCurrentTest("cesium_ext_structural_metadata_multiple_classes.gltf"); @@ -547,6 +820,9 @@ public void MultipleClassesTest() // Sample see https://github.com/CesiumGS/3d-tiles-samples/blob/main/glTF/EXT_structural_metadata/PropertyAttributesPointCloud/ + // Note in the sample an external json file (MetadataSchema.json) is used to define the schema, which is not supported + // in this library yet. + // This test uses the same schema but defines it in code instead. [Test(Description = "ext_structural_metadata with pointcloud and custom attributes")] public void CreatePointCloudWithCustomAttributesTest() { @@ -579,28 +855,40 @@ public void CreatePointCloudWithCustomAttributesTest() // -------------------------------------------------------------- var rootMetadata = model.UseStructuralMetadata(); + var schema = rootMetadata.UseEmbeddedSchema(); - // external references are problematic because the idea behind SharpGLTF is that all files are loaded into memory, so you don't - // need to track resources in disk while working with models. The whole mechanism is too complex to be worth the pain of implementing it. - // so my idea is that the UseExternalSchema returns a ISchemaProxy interface or something like that, that has pretty much the same methods - // of an actual schema, so the API usage remains the same for both an embedded and an external schema. - - // var schemaUri = new Uri("MetadataSchema.json", UriKind.Relative); - // var schemaProxy = rootMetadata.UseExternalSchema(schemaUri); + var classA = schema + .UseClassMetadata("exampleMetadataClass") + .WithName("Example metadata class") + .WithDescription("An example metadata class for property attributes"); - var schema = rootMetadata.UseEmbeddedSchema("externalSchema"); + classA.UseProperty("intensity") + .WithName("Example intensity property") + .WithDescription("An example property for the intensity, with component type FLOAT32") + .WithFloat32Type(); - var externalClass = schema.UseClassMetadata("exampleMetadataClass"); + var speciesEnum = schema.UseEnumMetadata("classificationEnumType", ("MediumVegetation", 0), ("Buildings", 1)); - var propertyAttribute = rootMetadata.AddPropertyAttribute(externalClass); + classA + .UseProperty("classification") + .WithName("Example classification property") + .WithDescription("An example property for the classification, with the classificationEnumType") + .WithEnumeration(speciesEnum); - var intensityProperty = propertyAttribute.CreateProperty("intensity"); - intensityProperty.Attribute = "_INTENSITY"; - var classificationProperty = propertyAttribute.CreateProperty("classification"); - classificationProperty.Attribute = "_CLASSIFICATION"; + var propertyAttribute = rootMetadata.AddPropertyAttribute(classA); + var intensityAttribute = propertyAttribute.CreateProperty("intensity"); + intensityAttribute.Attribute = "_INTENSITY"; + var classificationAttribute = propertyAttribute.CreateProperty("classification"); + classificationAttribute.Attribute = "_CLASSIFICATION"; var ctx = new ValidationResult(model, ValidationMode.Strict, true); + + foreach (var primitive in model.LogicalMeshes[0].Primitives) + { + primitive.AddPropertyAttribute(propertyAttribute); + } + model.AttachToCurrentTest("cesium_ext_structural_metadata_with_pointcloud_attributes.glb"); model.AttachToCurrentTest("cesium_ext_structural_metadata_with_pointcloud_attributes.gltf"); model.AttachToCurrentTest("cesium_ext_structural_metadata_with_pointcloud_attributes.plotly"); diff --git a/tests/SharpGLTF.Cesium.Tests/GenericTests.cs b/tests/SharpGLTF.Cesium.Tests/GenericTests.cs new file mode 100644 index 00000000..b2c4cd6b --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/GenericTests.cs @@ -0,0 +1,44 @@ +using NUnit.Framework; +using SharpGLTF.Schema2; +using SharpGLTF.Validation; +using System; + +namespace SharpGLTF +{ + + [Category("Toolkit.Scenes")] + public class ExtStructuralMetadataTests + { + [SetUp] + public void SetUp() + { + Tiles3DExtensions.RegisterExtensions(); + } + + // Test files are from https://github.com/CesiumGS/3d-tiles-validator/tree/main/specs/data/gltfExtensions/ + + [Test(Description = "Reads generic 3D Tiles glTF's")] + [TestCase("FeatureIdAttributeAndPropertyTableFeatureIdNotInRange.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributePropertyTableInvalidValue.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributePropertyTableWithoutPropertyTables.gltf", typeof(ModelException))] + [TestCase("FeatureIdAttributePropertyTableWithoutStructuralMetadata.gltf", typeof(ModelException))] + [TestCase("FeatureIdTextureAndPropertyTableFeatureIdNotInRange.gltf", typeof(ModelException))] + [TestCase("ValidFeatureIdAttributeAndPropertyTable.gltf", null)] + [TestCase("ValidFeatureIdTextureAndPropertyTable.gltf", null)] + public void ReadGenericFiles(string file, Type exception = null) + { + var fileName = $"./testfixtures/{file}"; + + if (exception != null) + { + Assert.Throws(exception, delegate { ModelRoot.Load(fileName); }); + } + else + { + var model = ModelRoot.Load(fileName); + var ctx = new ValidationResult(model, ValidationMode.Strict, true); + model.ValidateContent(ctx.GetContext()); + } + } + } +} diff --git a/tests/SharpGLTF.Cesium.Tests/SharpGLTF.Cesium.Tests.csproj b/tests/SharpGLTF.Cesium.Tests/SharpGLTF.Cesium.Tests.csproj index e7183c61..dd63971b 100644 --- a/tests/SharpGLTF.Cesium.Tests/SharpGLTF.Cesium.Tests.csproj +++ b/tests/SharpGLTF.Cesium.Tests/SharpGLTF.Cesium.Tests.csproj @@ -26,6 +26,14 @@ + + + + + + + + PreserveNewest diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributeAndPropertyTableFeatureIdNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributeAndPropertyTableFeatureIdNotInRange.gltf new file mode 100644 index 00000000..1b571af1 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributeAndPropertyTableFeatureIdNotInRange.gltf @@ -0,0 +1,141 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "FeatureIdAttributeAndPropertyTableSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class", + "properties" : { + "example_VEC3_FLOAT32" : { + "name" : "Example VEC3 FLOAT32 property", + "description" : "An example property, with type VEC3, with component type FLOAT32", + "type" : "VEC3", + "componentType" : "FLOAT32" + } + } + } + } + }, + "propertyTables" : [ { + "name" : "Example property table", + "class" : "exampleMetadataClass", + "count" : 4, + "properties" : { + "example_VEC3_FLOAT32" : { + "values" : 4 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_mesh_features", "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5120, + "count" : 16, + "type" : "SCALAR", + "max" : [ 123 ], + "min" : [ -123 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/hQAAAIUAAACFAAAAhQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAewAAAHsAAAB7AAAAewAAAA==", + "byteLength" : 496 + }, { + "uri" : "data:application/gltf-buffer;base64,AAAAAM3MzD3NzEw+AACAP83MjD+amZk/AAAAQGZmBkDNzAxAAABAQGZmRkDNzExA", + "byteLength" : 48 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 48 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0, + "propertyTable" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributePropertyTableInvalidValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributePropertyTableInvalidValue.gltf new file mode 100644 index 00000000..b9641116 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributePropertyTableInvalidValue.gltf @@ -0,0 +1,141 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "FeatureIdAttributeAndPropertyTableSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class", + "properties" : { + "example_VEC3_FLOAT32" : { + "name" : "Example VEC3 FLOAT32 property", + "description" : "An example property, with type VEC3, with component type FLOAT32", + "type" : "VEC3", + "componentType" : "FLOAT32" + } + } + } + } + }, + "propertyTables" : [ { + "name" : "Example property table", + "class" : "exampleMetadataClass", + "count" : 4, + "properties" : { + "example_VEC3_FLOAT32" : { + "values" : 4 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_mesh_features", "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + }, { + "uri" : "data:application/gltf-buffer;base64,AAAAAM3MzD3NzEw+AACAP83MjD+amZk/AAAAQGZmBkDNzAxAAABAQGZmRkDNzExA", + "byteLength" : 48 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 48 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0, + "propertyTable" : 12345 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributePropertyTableWithoutPropertyTables.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributePropertyTableWithoutPropertyTables.gltf new file mode 100644 index 00000000..194b1f42 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributePropertyTableWithoutPropertyTables.gltf @@ -0,0 +1,131 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "FeatureIdAttributeAndPropertyTableSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class", + "properties" : { + "example_VEC3_FLOAT32" : { + "name" : "Example VEC3 FLOAT32 property", + "description" : "An example property, with type VEC3, with component type FLOAT32", + "type" : "VEC3", + "componentType" : "FLOAT32" + } + } + } + } + } + } + }, + "extensionsUsed" : [ "EXT_mesh_features", "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + }, { + "uri" : "data:application/gltf-buffer;base64,AAAAAM3MzD3NzEw+AACAP83MjD+amZk/AAAAQGZmBkDNzAxAAABAQGZmRkDNzExA", + "byteLength" : 48 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 48 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0, + "propertyTable" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributePropertyTableWithoutStructuralMetadata.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributePropertyTableWithoutStructuralMetadata.gltf new file mode 100644 index 00000000..b87d92d0 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdAttributePropertyTableWithoutStructuralMetadata.gltf @@ -0,0 +1,110 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + }, { + "uri" : "data:application/gltf-buffer;base64,AAAAAM3MzD3NzEw+AACAP83MjD+amZk/AAAAQGZmBkDNzAxAAABAQGZmRkDNzExA", + "byteLength" : 48 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 48 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0, + "propertyTable" : 12345 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdTextureAndPropertyTableFeatureIdNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdTextureAndPropertyTableFeatureIdNotInRange.gltf new file mode 100644 index 00000000..b01293a6 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/FeatureIdTextureAndPropertyTableFeatureIdNotInRange.gltf @@ -0,0 +1,180 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "FeatureIdTextureAndPropertyTableSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building components", + "properties" : { + "component" : { + "name" : "Component", + "type" : "STRING" + }, + "yearBuilt" : { + "name" : "Year Built", + "type" : "SCALAR", + "componentType" : "INT16" + } + } + } + } + }, + "propertyTables" : [ { + "name" : "Example property table", + "class" : "buildingComponents", + "count" : 4, + "properties" : { + "component" : { + "values" : 4, + "stringOffsets" : 5 + }, + "yearBuilt" : { + "values" : 6 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_mesh_features", "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + }, { + "uri" : "data:application/gltf-buffer;base64,V2FsbERvb3JSb29mV2luZG93AAAAAAAABAAAAAgAAAAMAAAAEgAAAKgHzAfBB9IH", + "byteLength" : 48 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 18 + }, { + "buffer" : 1, + "byteOffset" : 20, + "byteLength" : 20 + }, { + "buffer" : 1, + "byteOffset" : 40, + "byteLength" : 8 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAABgSURBVDhPpczLEYAgDADR0IfctP/KtAWcZUYGlU8S9rDHJ+e2p5WErSAZIC9SAPIgL4CsyA8gC9IESIt0AdIgQ4BmyBSgEaICqIeoAWohJoC+iBmgGnEB9CCBibMrHnIDWhGma1gYMlcAAAAASUVORK5CYII=", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 2, + "texture" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "propertyTable" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/README.md b/tests/SharpGLTF.Cesium.Tests/testfixtures/README.md new file mode 100644 index 00000000..3ac62ce7 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/README.md @@ -0,0 +1,14 @@ +# Test fixtures + +This directory contains glTF files used for testing 3D Tiles functionality. + +3D Tiles Test fixtures are obtained from https://github.com/CesiumGS/3d-tiles-validator/tree/main/specs/data/gltfExtensions + +## Validating + +The files can be validated using the 3D Tiles Validator: + +``` +$ git clone https://github.com/CesiumGS/3d-tiles-validator +$ npx ts-node ./3d-tiles-validator/src/main.ts --tileContentFile test.gltf +``` diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/ValidFeatureIdAttributeAndPropertyTable.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/ValidFeatureIdAttributeAndPropertyTable.gltf new file mode 100644 index 00000000..3265d734 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/ValidFeatureIdAttributeAndPropertyTable.gltf @@ -0,0 +1,141 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "FeatureIdAttributeAndPropertyTableSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class", + "properties" : { + "example_VEC3_FLOAT32" : { + "name" : "Example VEC3 FLOAT32 property", + "description" : "An example property, with type VEC3, with component type FLOAT32", + "type" : "VEC3", + "componentType" : "FLOAT32" + } + } + } + } + }, + "propertyTables" : [ { + "name" : "Example property table", + "class" : "exampleMetadataClass", + "count" : 4, + "properties" : { + "example_VEC3_FLOAT32" : { + "values" : 4 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_mesh_features", "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + }, { + "uri" : "data:application/gltf-buffer;base64,AAAAAM3MzD3NzEw+AACAP83MjD+amZk/AAAAQGZmBkDNzAxAAABAQGZmRkDNzExA", + "byteLength" : 48 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 48 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0, + "propertyTable" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/ValidFeatureIdTextureAndPropertyTable.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/ValidFeatureIdTextureAndPropertyTable.gltf new file mode 100644 index 00000000..a65f6996 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/ValidFeatureIdTextureAndPropertyTable.gltf @@ -0,0 +1,180 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "FeatureIdTextureAndPropertyTableSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building components", + "properties" : { + "component" : { + "name" : "Component", + "type" : "STRING" + }, + "yearBuilt" : { + "name" : "Year Built", + "type" : "SCALAR", + "componentType" : "INT16" + } + } + } + } + }, + "propertyTables" : [ { + "name" : "Example property table", + "class" : "buildingComponents", + "count" : 4, + "properties" : { + "component" : { + "values" : 4, + "stringOffsets" : 5 + }, + "yearBuilt" : { + "values" : 6 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_mesh_features", "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + }, { + "uri" : "data:application/gltf-buffer;base64,V2FsbERvb3JSb29mV2luZG93AAAAAAAABAAAAAgAAAAMAAAAEgAAAKgHzAfBB9IH", + "byteLength" : 48 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 18 + }, { + "buffer" : 1, + "byteOffset" : 20, + "byteLength" : 20 + }, { + "buffer" : 1, + "byteOffset" : 40, + "byteLength" : 8 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "propertyTable" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/instanceFeatures/InstanceFeaturesFeatureIdAttributeInvalidValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/instanceFeatures/InstanceFeaturesFeatureIdAttributeInvalidValue.gltf new file mode 100644 index 00000000..d8e3526d --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/instanceFeatures/InstanceFeaturesFeatureIdAttributeInvalidValue.gltf @@ -0,0 +1,179 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "GpuInstancesMetadataSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class", + "properties" : { + "example_STRING" : { + "name" : "Example STRING property", + "description" : "An example property, with component type STRING", + "type" : "STRING" + } + } + } + } + }, + "propertyTables" : [ { + "name" : "Example property table", + "class" : "exampleMetadataClass", + "count" : 10, + "properties" : { + "example_STRING" : { + "values" : 7, + "stringOffsets" : 8 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata", "EXT_mesh_gpu_instancing", "EXT_instance_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5125, + "count" : 36, + "type" : "SCALAR", + "max" : [ 23 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 24, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 1.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 24, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 1.0 ], + "min" : [ -1.0, -1.0, -1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 10, + "type" : "VEC3", + "max" : [ 10.0, 10.0, 10.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 10, + "type" : "VEC4", + "max" : [ 0.733, 0.462, 0.191, 1.0 ], + "min" : [ 0.0, 0.0, 0.0, 0.462 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 10, + "type" : "VEC3", + "max" : [ 2.0, 2.0, 2.0 ], + "min" : [ 1.0, 1.0, 1.0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 10, + "type" : "SCALAR", + "max" : [ 9 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAAAAAIAAAABAAAAAAAAAAMAAAACAAAABAAAAAYAAAAFAAAABAAAAAcAAAAGAAAACAAAAAoAAAAJAAAACAAAAAsAAAAKAAAADAAAAA4AAAANAAAADAAAAA8AAAAOAAAAEAAAABIAAAARAAAAEAAAABMAAAASAAAAFAAAABYAAAAVAAAAFAAAABcAAAAWAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAACAPwAAgD8AAIA/AAAAAAAAgD8AAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA", + "byteLength" : 720 + }, { + "uri" : "data:application/gltf-buffer;base64,AAAAAAAAAAAAAAAA5DiOP+Q4jj/kOI4/5DgOQOQ4DkDkOA5AVlVVQFZVVUBWVVVA5DiOQOQ4jkDkOI5AHcexQB3HsUAdx7FAVlXVQFZV1UBWVdVAjuP4QI7j+ECO4/hA5DgOQeQ4DkHkOA5BAAAgQQAAIEEAACBBAAAAAAAAAAAAAAAAAACAP92ZzD0Q9YA9B0HVPHcffj/QGUs+AAMAPrywUz3rhHg/HXaWPuWqPT4f05w9Y0VvP3UqxT6+ing+IIHNPZiDYj+d+vA+w+KXPqEr+z1ub1I/DaEMP/RFsT6bkxI+REU/P9m0Hj+hD8g+H2slPgpNKT/WdC4/P+rbPqHVNT462RA/46U7P0SL7D6BlUM+RIvsPgAAgD8AAIA/AACAP+Q4jj/kOI4/5DiOP8dxnD/HcZw/x3GcP6uqqj+rqqo/q6qqP47juD+O47g/juO4P3Icxz9yHMc/chzHP1ZV1T9WVdU/VlXVPzmO4z85juM/OY7jPxzH8T8cx/E/HMfxPwAAAEAAAABAAAAAQAkACAAHAAYABQAEAAMAAgABAAAA", + "byteLength" : 420 + }, { + "uri" : "data:application/gltf-buffer;base64,emVyb29uZXR3b3RocmVlZm91cmZpdmVzaXhzZXZlbmVpZ2h0bmluZQAAAAAEAAAABwAAAAoAAAAPAAAAEwAAABcAAAAaAAAAHwAAACQAAAAoAAAA", + "byteLength" : 84 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 144, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 144, + "byteLength" : 288, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 288, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 120 + }, { + "buffer" : 1, + "byteOffset" : 120, + "byteLength" : 160 + }, { + "buffer" : 1, + "byteOffset" : 280, + "byteLength" : 120 + }, { + "buffer" : 1, + "byteOffset" : 400, + "byteLength" : 20 + }, { + "buffer" : 2, + "byteOffset" : 0, + "byteLength" : 40 + }, { + "buffer" : 2, + "byteOffset" : 40, + "byteLength" : 44 + } ], + "meshes" : [ { + "primitives" : [ { + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2 + }, + "indices" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "extensions" : { + "EXT_mesh_gpu_instancing" : { + "attributes" : { + "TRANSLATION" : 3, + "ROTATION" : 4, + "SCALE" : 5, + "_FEATURE_ID_0" : 6 + } + }, + "EXT_instance_features" : { + "featureIds" : [ { + "featureCount" : 10, + "attribute" : 12345, + "propertyTable" : 0 + } ] + } + }, + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/instanceFeatures/InstanceFeaturesWithoutMeshGpuInstancing.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/instanceFeatures/InstanceFeaturesWithoutMeshGpuInstancing.gltf new file mode 100644 index 00000000..d6fdc89f --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/instanceFeatures/InstanceFeaturesWithoutMeshGpuInstancing.gltf @@ -0,0 +1,171 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "GpuInstancesMetadataSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class", + "properties" : { + "example_STRING" : { + "name" : "Example STRING property", + "description" : "An example property, with component type STRING", + "type" : "STRING" + } + } + } + } + }, + "propertyTables" : [ { + "name" : "Example property table", + "class" : "exampleMetadataClass", + "count" : 10, + "properties" : { + "example_STRING" : { + "values" : 7, + "stringOffsets" : 8 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata", "EXT_mesh_gpu_instancing", "EXT_instance_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5125, + "count" : 36, + "type" : "SCALAR", + "max" : [ 23 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 24, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 1.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 24, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 1.0 ], + "min" : [ -1.0, -1.0, -1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 10, + "type" : "VEC3", + "max" : [ 10.0, 10.0, 10.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 10, + "type" : "VEC4", + "max" : [ 0.733, 0.462, 0.191, 1.0 ], + "min" : [ 0.0, 0.0, 0.0, 0.462 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 10, + "type" : "VEC3", + "max" : [ 2.0, 2.0, 2.0 ], + "min" : [ 1.0, 1.0, 1.0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 10, + "type" : "SCALAR", + "max" : [ 9 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAAAAAIAAAABAAAAAAAAAAMAAAACAAAABAAAAAYAAAAFAAAABAAAAAcAAAAGAAAACAAAAAoAAAAJAAAACAAAAAsAAAAKAAAADAAAAA4AAAANAAAADAAAAA8AAAAOAAAAEAAAABIAAAARAAAAEAAAABMAAAASAAAAFAAAABYAAAAVAAAAFAAAABcAAAAWAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAACAPwAAgD8AAIA/AAAAAAAAgD8AAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA", + "byteLength" : 720 + }, { + "uri" : "data:application/gltf-buffer;base64,AAAAAAAAAAAAAAAA5DiOP+Q4jj/kOI4/5DgOQOQ4DkDkOA5AVlVVQFZVVUBWVVVA5DiOQOQ4jkDkOI5AHcexQB3HsUAdx7FAVlXVQFZV1UBWVdVAjuP4QI7j+ECO4/hA5DgOQeQ4DkHkOA5BAAAgQQAAIEEAACBBAAAAAAAAAAAAAAAAAACAP92ZzD0Q9YA9B0HVPHcffj/QGUs+AAMAPrywUz3rhHg/HXaWPuWqPT4f05w9Y0VvP3UqxT6+ing+IIHNPZiDYj+d+vA+w+KXPqEr+z1ub1I/DaEMP/RFsT6bkxI+REU/P9m0Hj+hD8g+H2slPgpNKT/WdC4/P+rbPqHVNT462RA/46U7P0SL7D6BlUM+RIvsPgAAgD8AAIA/AACAP+Q4jj/kOI4/5DiOP8dxnD/HcZw/x3GcP6uqqj+rqqo/q6qqP47juD+O47g/juO4P3Icxz9yHMc/chzHP1ZV1T9WVdU/VlXVPzmO4z85juM/OY7jPxzH8T8cx/E/HMfxPwAAAEAAAABAAAAAQAkACAAHAAYABQAEAAMAAgABAAAA", + "byteLength" : 420 + }, { + "uri" : "data:application/gltf-buffer;base64,emVyb29uZXR3b3RocmVlZm91cmZpdmVzaXhzZXZlbmVpZ2h0bmluZQAAAAAEAAAABwAAAAoAAAAPAAAAEwAAABcAAAAaAAAAHwAAACQAAAAoAAAA", + "byteLength" : 84 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 144, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 144, + "byteLength" : 288, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 288, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 120 + }, { + "buffer" : 1, + "byteOffset" : 120, + "byteLength" : 160 + }, { + "buffer" : 1, + "byteOffset" : 280, + "byteLength" : 120 + }, { + "buffer" : 1, + "byteOffset" : 400, + "byteLength" : 20 + }, { + "buffer" : 2, + "byteOffset" : 0, + "byteLength" : 40 + }, { + "buffer" : 2, + "byteOffset" : 40, + "byteLength" : 44 + } ], + "meshes" : [ { + "primitives" : [ { + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2 + }, + "indices" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "extensions" : { + "EXT_instance_features" : { + "featureIds" : [ { + "featureCount" : 10, + "attribute" : 0, + "propertyTable" : 0 + } ] + } + }, + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/instanceFeatures/ValidInstanceFeatures.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/instanceFeatures/ValidInstanceFeatures.gltf new file mode 100644 index 00000000..aa40c126 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/instanceFeatures/ValidInstanceFeatures.gltf @@ -0,0 +1,179 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "GpuInstancesMetadataSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class", + "properties" : { + "example_STRING" : { + "name" : "Example STRING property", + "description" : "An example property, with component type STRING", + "type" : "STRING" + } + } + } + } + }, + "propertyTables" : [ { + "name" : "Example property table", + "class" : "exampleMetadataClass", + "count" : 10, + "properties" : { + "example_STRING" : { + "values" : 7, + "stringOffsets" : 8 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata", "EXT_mesh_gpu_instancing", "EXT_instance_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5125, + "count" : 36, + "type" : "SCALAR", + "max" : [ 23 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 24, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 1.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 24, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 1.0 ], + "min" : [ -1.0, -1.0, -1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 10, + "type" : "VEC3", + "max" : [ 10.0, 10.0, 10.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 10, + "type" : "VEC4", + "max" : [ 0.733, 0.462, 0.191, 1.0 ], + "min" : [ 0.0, 0.0, 0.0, 0.462 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 10, + "type" : "VEC3", + "max" : [ 2.0, 2.0, 2.0 ], + "min" : [ 1.0, 1.0, 1.0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 10, + "type" : "SCALAR", + "max" : [ 9 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAAAAAIAAAABAAAAAAAAAAMAAAACAAAABAAAAAYAAAAFAAAABAAAAAcAAAAGAAAACAAAAAoAAAAJAAAACAAAAAsAAAAKAAAADAAAAA4AAAANAAAADAAAAA8AAAAOAAAAEAAAABIAAAARAAAAEAAAABMAAAASAAAAFAAAABYAAAAVAAAAFAAAABcAAAAWAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAACAPwAAgD8AAIA/AAAAAAAAgD8AAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA", + "byteLength" : 720 + }, { + "uri" : "data:application/gltf-buffer;base64,AAAAAAAAAAAAAAAA5DiOP+Q4jj/kOI4/5DgOQOQ4DkDkOA5AVlVVQFZVVUBWVVVA5DiOQOQ4jkDkOI5AHcexQB3HsUAdx7FAVlXVQFZV1UBWVdVAjuP4QI7j+ECO4/hA5DgOQeQ4DkHkOA5BAAAgQQAAIEEAACBBAAAAAAAAAAAAAAAAAACAP92ZzD0Q9YA9B0HVPHcffj/QGUs+AAMAPrywUz3rhHg/HXaWPuWqPT4f05w9Y0VvP3UqxT6+ing+IIHNPZiDYj+d+vA+w+KXPqEr+z1ub1I/DaEMP/RFsT6bkxI+REU/P9m0Hj+hD8g+H2slPgpNKT/WdC4/P+rbPqHVNT462RA/46U7P0SL7D6BlUM+RIvsPgAAgD8AAIA/AACAP+Q4jj/kOI4/5DiOP8dxnD/HcZw/x3GcP6uqqj+rqqo/q6qqP47juD+O47g/juO4P3Icxz9yHMc/chzHP1ZV1T9WVdU/VlXVPzmO4z85juM/OY7jPxzH8T8cx/E/HMfxPwAAAEAAAABAAAAAQAkACAAHAAYABQAEAAMAAgABAAAA", + "byteLength" : 420 + }, { + "uri" : "data:application/gltf-buffer;base64,emVyb29uZXR3b3RocmVlZm91cmZpdmVzaXhzZXZlbmVpZ2h0bmluZQAAAAAEAAAABwAAAAoAAAAPAAAAEwAAABcAAAAaAAAAHwAAACQAAAAoAAAA", + "byteLength" : 84 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 144, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 144, + "byteLength" : 288, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 288, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 120 + }, { + "buffer" : 1, + "byteOffset" : 120, + "byteLength" : 160 + }, { + "buffer" : 1, + "byteOffset" : 280, + "byteLength" : 120 + }, { + "buffer" : 1, + "byteOffset" : 400, + "byteLength" : 20 + }, { + "buffer" : 2, + "byteOffset" : 0, + "byteLength" : 40 + }, { + "buffer" : 2, + "byteOffset" : 40, + "byteLength" : 44 + } ], + "meshes" : [ { + "primitives" : [ { + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2 + }, + "indices" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "extensions" : { + "EXT_mesh_gpu_instancing" : { + "attributes" : { + "TRANSLATION" : 3, + "ROTATION" : 4, + "SCALE" : 5, + "_FEATURE_ID_0" : 6 + } + }, + "EXT_instance_features" : { + "featureIds" : [ { + "featureCount" : 10, + "attribute" : 0, + "propertyTable" : 0 + } ] + } + }, + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAccessorNormalized.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAccessorNormalized.gltf new file mode 100644 index 00000000..b8cc4759 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAccessorNormalized.gltf @@ -0,0 +1,103 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ], + "normalized": true + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAccessorNotScalar.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAccessorNotScalar.gltf new file mode 100644 index 00000000..3429fa6a --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAccessorNotScalar.gltf @@ -0,0 +1,102 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 2 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAttributeInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAttributeInvalidType.gltf new file mode 100644 index 00000000..0b7e783c --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAttributeInvalidType.gltf @@ -0,0 +1,102 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : "NOT_A_NUMBER" + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAttributeInvalidValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAttributeInvalidValue.gltf new file mode 100644 index 00000000..bc53e41b --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeAttributeInvalidValue.gltf @@ -0,0 +1,102 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 12345 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountInvalidType.gltf new file mode 100644 index 00000000..934cfdde --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountInvalidType.gltf @@ -0,0 +1,102 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : "NOT_AN_INTEGER", + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountInvalidValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountInvalidValue.gltf new file mode 100644 index 00000000..420e3b16 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountInvalidValue.gltf @@ -0,0 +1,102 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : -12345, + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountMismatch.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountMismatch.gltf new file mode 100644 index 00000000..94d88370 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountMismatch.gltf @@ -0,0 +1,102 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 1, + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountMismatchForNullFeatureId.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountMismatchForNullFeatureId.gltf new file mode 100644 index 00000000..749b2ed1 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountMismatchForNullFeatureId.gltf @@ -0,0 +1,103 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 2, + "attribute" : 0, + "nullFeatureId": 1 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountMissing.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountMissing.gltf new file mode 100644 index 00000000..4ae80ac2 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeFeatureCountMissing.gltf @@ -0,0 +1,101 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeLabelInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeLabelInvalidType.gltf new file mode 100644 index 00000000..6f875c04 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeLabelInvalidType.gltf @@ -0,0 +1,103 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "label": 12345, + "featureCount" : 4, + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeLabelInvalidValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeLabelInvalidValue.gltf new file mode 100644 index 00000000..ab122b89 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeLabelInvalidValue.gltf @@ -0,0 +1,103 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "label": "NOT:A:VALID/IDENTIFIER", + "featureCount" : 4, + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeNullFeatureIdInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeNullFeatureIdInvalidType.gltf new file mode 100644 index 00000000..03e44702 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeNullFeatureIdInvalidType.gltf @@ -0,0 +1,103 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "nullFeatureId": "NOT_A_NUMBER", + "featureCount" : 4, + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeNullFeatureIdInvalidValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeNullFeatureIdInvalidValue.gltf new file mode 100644 index 00000000..d87f5c5e --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdAttributeNullFeatureIdInvalidValue.gltf @@ -0,0 +1,103 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "nullFeatureId": -12345, + "featureCount" : 4, + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureFeatureCountMismatch.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureFeatureCountMismatch.gltf new file mode 100644 index 00000000..aee7749a --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureFeatureCountMismatch.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAIvklEQVR42u3csW5URxsG4BHBRRoklxROEQlSRCJCKShoXFJZiDSpQEqX2pYii8ZVlDZF7oNcAAURDREdpCEXQKoIlAKFEE3O4s0KoV17zxm8Z+Z8j6zvj6Nfj7Q663k968y8aXd3NxtjYk6a/U9OafDwPN+uFwA8LwA8QJ4XAO/Mw26+6Garm6vd/NbzBfA8X79fGQCXuvll/v1P3XzZ8wXwPF+/X+sjwL/zJBm6BeF5vk6/VgC8nG8nhr4Anufr9GsFwA/d/FzwAnier9OfGgC/d/NdwV8heZ6v158YAH908203/wx8ATzP1+1XBsDsL4hfdfNq4H+H5Hm+fr8yAD6Z/Z/vTZ8XwPN8/d5JQJ53EtAD5HkB4AHyfLwAMMboA5CgPO8jgAfI8wLAA+R5fQDuU/O8PgD3qXleH4D71DyvD8B9ap7XB+A+Nc/rA+B5Xh8Az/P6AHie1wfA87w+AJ7nHQXmeV4A8DyvD8AYow+A53kfAXieFwA8z+sD4HleHwDP8/oAeJ7XB8DzvD4Anuf1AfA8rw+A53l9ADzP6wPgeV4fAM/zjgLzPC8AeJ7XB2CMOaEPIBV88TzfrhcAPC8APECeFwDvfj3p5lI3W91c7eZhzxfA83z1fnUA3O7mx/n333fzdc8XwPN89X51AHzazd/z7//s5vOeL4Dn+er96gD4+JR/P+0F8DxfvV8dAOm9f9/q+QJ4nq/e2wHwvB3Akq/Punk5//6v+V8U+7wAnuer96sD4Jv5Xw///yvi7Z4vgOf56v3qAPh1/pfEj+bp8aTnC+B5vnrvJCDPOwnoAfK8APAAeT5eABhj9AFIUJ73EcAD5HkB4AHyfOAAcJ+a5/UBLE4SuU/N85Pz+gB4PrB3G5DnA3t9ADwf2NsB8LwdwJIv96l5fvJeHwDPB/b6AHg+sHcSkOedBPQAeV4AeIA8Hy8AjDH6AMZLsJQHD+83IN/6RwABIAB4ASAABABfSwBs8j7zkh/sK1dyfvw459evc370KOfLl/stoFB+7PePb9bX0Qew5Af76dOcb906/v7OnePF0GcBhfJjv398s76OPoA1trqz34QlW+hJ+7HfP75ZX8dtwBN+8M+dy/nu3Zzv3Ru2gEL4sd8/vllfRx/Aih/+8+dzfvEi5zdvcr55s/8CCuPHfv/4Zn31O4DZ3LiR8/Pnw7fQk/d+A/IffAewyfvM/gbw4f8G4D4830wfwJIf7GfPjv9T2Oz769dzvn+/3wIK5cd+//hmfR19AEt+sK9dO/5PYbPffA8e5HzxYr8FFMqP/f7xzXonAZ0E5J0EFAACgBcAAkAA8PECwBijD8AOwA6A9xFAAAgAXgAIAAHABw4AfQD6AHh9AGkT95n1AegD4Efx+gD0AfCBvT4AfQC824Bp3PvM+gD0AfCjeH0A+gB4O4A07n1mfwPQB8CP4vUB6APgA3t9APoA+MDeSUAnAXknAQWAAOAFgAAQAHy8ADDG6AOwA7AD4H0EEAACgBcAAkAA8IEDQB+APgBeH0DaxH1mfQD6APhRvD4AfQB8YK8PQB8A7zZgGvc+sz4AfQD8KF4fgD4A3g4gjXuf2d8A9AHwo3h9APoA+MBeH4A+AD6wdxLQSUDeSUABIAB4ASAABAAfLwCMMfoAJCjP+wjgAfK8APAAeT5wALhPzfP6ABYnidyn5vnJ+eQ+Nc/H9cltKp6P65P71Dwf19sB8LwdwJIv96l5fvI+uU/N83F9cp+a5+N6JwF53klAD5DnBYAHyPPxAsAYow9AgvK8jwAeIM8LAA+Q5wMHgPvUPK8PYHGSyH1qnp+c1wfA84G924A8H9jrA+D5wN4OgOftAJZ8uU/N85P3+gB4PrDXB8Dzgb2TgDzvJKAHyPMCwAPk+XgBYIzRByBB+UH+6Oho8NTgfQSwAHgBIAAsAF4ACIDjL/ep+TX9qsV1eHiYt7e3By/gTfnI758+AL7YL1tYBwcHeWdn5+2llCELeJM+8vunD4Av9ssW1oULF/Le3t7gBbxJH/n9cxuQL/bLFtb+/v7bfw5dwJv0kd8/fQB8sT9pgQ1dwJv0kd8/OwD+THYAzQeAPoDkPjW/lp9kAOgDSO5T82v5SQaAPoDkPjW/lp9kAOgDcBKOdxLQUWALgBcAAsAC4AXARAPAGKMPwG9A3g7ARwALgBcAAsAC4AVA4ABwH57XB6APYHGSyH14vkcA6ANI+gD4GF4fQLvebUC+2OsDaNfrA+CLvT6Adr0dAH8mOwB9AK3vANyH5/UBTP790wfAF3t9AO16fQB8sdcH0K53EpB3EtBJQAuAFwACwALgBUC8ADDG6APwG5C3A/ARwALgBYAAsAB4ARA4ANyH5/UB6ANYnCRyH57vEQD6AJI+AD6G1wfQrncbkC/2+gDa9foA+GKvD6BdbwfAn8kOQB9A6zsA9+F5fQCTf//0AfDFXh9Au14fAF/s9QG0650E5J0EdBLQAuAFgACwAHgBEC8AjDH6APwG5O0AfASwAHgBIAAsAF4ABA4A9+F5fQD6ABYnidyH53sEgD6ApA+Aj+H1AbTr3Qbki70+gHa9PgC+2OsDaNfbAfBnsgPQB9D6DsB9eF4fwOTfP30AfLHXB9Cu1wfAF3t9AO16JwF5JwGdBLQAeAEgACwAXgDECwBjjD4AvwF5OwAfASwAXgAIAAuAFwCBA8B9eF4fgD6AxUki9+H5HgGgDyDpA+BjeH0A7Xq3Aflirw+gXa8PgC/2+gDa9XYA/JnsAPQBtL4DcB+e1wcw+fdPHwBf7PUBtOv1AfDFXh9Au95JQN5JQCcBLQBeAAgAC4AXAPECwBijD8BvQN4OwEcAC4AXAALAAuAFQOAAcB+e1wegD2Bxksh9eL5HAOgDSPoA+BheH0C73m1AvtjrA2jX6wPgi70+gHa9HQB/JjsAfQCt7wDch+f1AUz+/dMHwBd7fQDten0AfLHXB9CudxKQdxLQSUALgBcAAsAC4AVAqPfvPyVxz6xUBN7bAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 1, + "texture" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureSamplerInvalidFilterMode.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureSamplerInvalidFilterMode.gltf new file mode 100644 index 00000000..5ead167e --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureSamplerInvalidFilterMode.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9729, + "minFilter" : 9729 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsInvalidElementType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsInvalidElementType.gltf new file mode 100644 index 00000000..83bf369a --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsInvalidElementType.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : 0, + "channels" : [0, "NOT_A_NUMBER"] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsInvalidType.gltf new file mode 100644 index 00000000..60a2f4ca --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsInvalidType.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : 0, + "channels" : "NOT_AN_ARRAY" + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsTooManyChannels.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsTooManyChannels.gltf new file mode 100644 index 00000000..2e6cf4a7 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsTooManyChannels.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : 0, + "channels" : [0, 4, 1] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsTooManyElements.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsTooManyElements.gltf new file mode 100644 index 00000000..0ac5bb6f --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureChannelsTooManyElements.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : 0, + "channels" : [0, 1, 0, 1, 0, 1] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureImageDataInvalid.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureImageDataInvalid.gltf new file mode 100644 index 00000000..778154b9 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureImageDataInvalid.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAIvklEQVR42u3csW5URxsG4BHBRRoklxROEQlSRCJCKShoXFJZiDSpQEqX2pYii8ZVlDZF7oNcAAURDREdpCEXQKoIlAKFEE3O4s0KoV17zxm8Z+Z8j6zvj6Nfj7Q663k968y8aXd3NxtjYk6a/U9OafDwPN+uFwA8LwA8QJ4XAO/Mw26+6Garm6vd/NbzBfA8X79fGQCXuvll/v1P3XzZ8wXwPF+/X+sjwL/zJBm6BeF5vk6/VgC8nG8nhr4Anufr9GsFwA/d/FzwAnier9OfGgC/d/NdwV8heZ6v158YAH908203/wx8ATzP1+1XBsDsL4hfdfNq4H+H5Hm+fr8yAD6Z/Z/vTZ8XwPN8/d5JQJ53EtAD5HkB4AHyfLwAMMboA5CgPO8jgAfI8wLAA+R5fQDuU/O8PgD3qXleH4D71DyvD8B9ap7XB+A+Nc/rA+B5Xh8Az/P6AHie1wfA87w+AJ7nHQXmeV4A8DyvD8AYow+A53kfAXieFwA8z+sD4HleHwDP8/oAeJ7XB8DzvD4Anuf1AfA8rw+A53l9ADzP6wPgeV4fAM/zjgLzPC8AeJ7XB2CMOaEPIBV88TzfrhcAPC8APECeFwDvfj3p5lI3W91c7eZhzxfA83z1fnUA3O7mx/n333fzdc8XwPN89X51AHzazd/z7//s5vOeL4Dn+er96gD4+JR/P+0F8DxfvV8dAOm9f9/q+QJ4nq/e2wHwvB3Akq/Punk5//6v+V8U+7wAnuer96sD4Jv5Xw///yvi7Z4vgOf56v3qAPh1/pfEj+bp8aTnC+B5vnrvJCDPOwnoAfK8APAAeT5eABhj9AFIUJ73EcAD5HkB4AHyfOAAcJ+a5/UBLE4SuU/N85Pz+gB4PrB3G5DnA3t9ADwf2NsB8LwdwJIv96l5fvJeHwDPB/b6AHg+sHcSkOedBPQAeV4AeIA8Hy8AjDH6AMZLsJQHD+83IN/6RwABIAB4ASAABABfSwBs8j7zkh/sK1dyfvw459evc370KOfLl/stoFB+7PePb9bX0Qew5Af76dOcb906/v7OnePF0GcBhfJjv398s76OPoA1trqz34QlW+hJ+7HfP75ZX8dtwBN+8M+dy/nu3Zzv3Ru2gEL4sd8/vllfRx/Aih/+8+dzfvEi5zdvcr55s/8CCuPHfv/4Zn31O4DZ3LiR8/Pnw7fQk/d+A/IffAewyfvM/gbw4f8G4D4830wfwJIf7GfPjv9T2Oz769dzvn+/3wIK5cd+//hmfR19AEt+sK9dO/5PYbPffA8e5HzxYr8FFMqP/f7xzXonAZ0E5J0EFAACgBcAAkAA8PECwBijD8AOwA6A9xFAAAgAXgAIAAHABw4AfQD6AHh9AGkT95n1AegD4Efx+gD0AfCBvT4AfQC824Bp3PvM+gD0AfCjeH0A+gB4O4A07n1mfwPQB8CP4vUB6APgA3t9APoA+MDeSUAnAXknAQWAAOAFgAAQAHy8ADDG6AOwA7AD4H0EEAACgBcAAkAA8IEDQB+APgBeH0DaxH1mfQD6APhRvD4AfQB8YK8PQB8A7zZgGvc+sz4AfQD8KF4fgD4A3g4gjXuf2d8A9AHwo3h9APoA+MBeH4A+AD6wdxLQSUDeSUABIAB4ASAABAAfLwCMMfoAJCjP+wjgAfK8APAAeT5wALhPzfP6ABYnidyn5vnJ+eQ+Nc/H9cltKp6P65P71Dwf19sB8LwdwJIv96l5fvI+uU/N83F9cp+a5+N6JwF53klAD5DnBYAHyPPxAsAYow9AgvK8jwAeIM8LAA+Q5wMHgPvUPK8PYHGSyH1qnp+c1wfA84G924A8H9jrA+D5wN4OgOftAJZ8uU/N85P3+gB4PrDXB8Dzgb2TgDzvJKAHyPMCwAPk+XgBYIzRByBB+UH+6Oho8NTgfQSwAHgBIAAsAF4ACIDjL/ep+TX9qsV1eHiYt7e3By/gTfnI758+AL7YL1tYBwcHeWdn5+2llCELeJM+8vunD4Av9ssW1oULF/Le3t7gBbxJH/n9cxuQL/bLFtb+/v7bfw5dwJv0kd8/fQB8sT9pgQ1dwJv0kd8/OwD+THYAzQeAPoDkPjW/lp9kAOgDSO5T82v5SQaAPoDkPjW/lp9kAOgDcBKOdxLQUWALgBcAAsAC4AXARAPAGKMPwG9A3g7ARwALgBcAAsAC4AVA4ABwH57XB6APYHGSyH14vkcA6ANI+gD4GF4fQLvebUC+2OsDaNfrA+CLvT6Adr0dAH8mOwB9AK3vANyH5/UBTP790wfAF3t9AO16fQB8sdcH0K53EpB3EtBJQAuAFwACwALgBUC8ADDG6APwG5C3A/ARwALgBYAAsAB4ARA4ANyH5/UB6ANYnCRyH57vEQD6AJI+AD6G1wfQrncbkC/2+gDa9foA+GKvD6BdbwfAn8kOQB9A6zsA9+F5fQCTf//0AfDFXh9Au14fAF/s9QG0650E5J0EdBLQAuAFgACwAHgBEC8AjDH6APwG5O0AfASwAHgBIAAsAF4ABA4A9+F5fQD6ABYnidyH53sEgD6ApA+Aj+H1AbTr3Qbki70+gHa9PgC+2OsDaNfbAfBnsgPQB9D6DsB9eF4fwOTfP30AfLHXB9Cu1wfAF3t9AO16JwF5JwGdBLQAeAEgACwAXgDECwBjjD4AvwF5OwAfASwAXgAIAAuAFwCBA8B9eF4fgD6AxUki9+H5HgGgDyDpA+BjeH0A7Xq3Aflirw+gXa8PgC/2+gDa9XYA/JnsAPQBtL4DcB+e1wcw+fdPHwBf7PUBtOv1AfDFXh9Au95JQN5JQCcBLQBeAAgAC4AXAPECwBijD8BvQN4OwEcAC4AXAALAAuAFQOAAcB+e1wegD2Bxksh9eL5HAOgDSPoA+BheH0C73m1AvtjrA2jX6wPgi70+gHa9HQB/JjsAfQCt7wDch+f1AUz+/dMHwBd7fQDten0AfLHXB9CudxKQdxLQSUALgBcAAsAC4AVAqPfvPyVxz6xUBN7bAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,THIS_IS_NOT_VALID_IMAGE_DATA________________________________________________________________________________________________", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureIndexInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureIndexInvalidType.gltf new file mode 100644 index 00000000..b3949c45 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureIndexInvalidType.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : "NOT_A_NUMBER", + "texCoord" : 0, + "channels" : [ 0 ] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureIndexInvalidValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureIndexInvalidValue.gltf new file mode 100644 index 00000000..47e0d98f --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureIndexInvalidValue.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAIvklEQVR42u3csW5URxsG4BHBRRoklxROEQlSRCJCKShoXFJZiDSpQEqX2pYii8ZVlDZF7oNcAAURDREdpCEXQKoIlAKFEE3O4s0KoV17zxm8Z+Z8j6zvj6Nfj7Q663k968y8aXd3NxtjYk6a/U9OafDwPN+uFwA8LwA8QJ4XAO/Mw26+6Garm6vd/NbzBfA8X79fGQCXuvll/v1P3XzZ8wXwPF+/X+sjwL/zJBm6BeF5vk6/VgC8nG8nhr4Anufr9GsFwA/d/FzwAnier9OfGgC/d/NdwV8heZ6v158YAH908203/wx8ATzP1+1XBsDsL4hfdfNq4H+H5Hm+fr8yAD6Z/Z/vTZ8XwPN8/d5JQJ53EtAD5HkB4AHyfLwAMMboA5CgPO8jgAfI8wLAA+R5fQDuU/O8PgD3qXleH4D71DyvD8B9ap7XB+A+Nc/rA+B5Xh8Az/P6AHie1wfA87w+AJ7nHQXmeV4A8DyvD8AYow+A53kfAXieFwA8z+sD4HleHwDP8/oAeJ7XB8DzvD4Anuf1AfA8rw+A53l9ADzP6wPgeV4fAM/zjgLzPC8AeJ7XB2CMOaEPIBV88TzfrhcAPC8APECeFwDvfj3p5lI3W91c7eZhzxfA83z1fnUA3O7mx/n333fzdc8XwPN89X51AHzazd/z7//s5vOeL4Dn+er96gD4+JR/P+0F8DxfvV8dAOm9f9/q+QJ4nq/e2wHwvB3Akq/Punk5//6v+V8U+7wAnuer96sD4Jv5Xw///yvi7Z4vgOf56v3qAPh1/pfEj+bp8aTnC+B5vnrvJCDPOwnoAfK8APAAeT5eABhj9AFIUJ73EcAD5HkB4AHyfOAAcJ+a5/UBLE4SuU/N85Pz+gB4PrB3G5DnA3t9ADwf2NsB8LwdwJIv96l5fvJeHwDPB/b6AHg+sHcSkOedBPQAeV4AeIA8Hy8AjDH6AMZLsJQHD+83IN/6RwABIAB4ASAABABfSwBs8j7zkh/sK1dyfvw459evc370KOfLl/stoFB+7PePb9bX0Qew5Af76dOcb906/v7OnePF0GcBhfJjv398s76OPoA1trqz34QlW+hJ+7HfP75ZX8dtwBN+8M+dy/nu3Zzv3Ru2gEL4sd8/vllfRx/Aih/+8+dzfvEi5zdvcr55s/8CCuPHfv/4Zn31O4DZ3LiR8/Pnw7fQk/d+A/IffAewyfvM/gbw4f8G4D4830wfwJIf7GfPjv9T2Oz769dzvn+/3wIK5cd+//hmfR19AEt+sK9dO/5PYbPffA8e5HzxYr8FFMqP/f7xzXonAZ0E5J0EFAACgBcAAkAA8PECwBijD8AOwA6A9xFAAAgAXgAIAAHABw4AfQD6AHh9AGkT95n1AegD4Efx+gD0AfCBvT4AfQC824Bp3PvM+gD0AfCjeH0A+gB4O4A07n1mfwPQB8CP4vUB6APgA3t9APoA+MDeSUAnAXknAQWAAOAFgAAQAHy8ADDG6AOwA7AD4H0EEAACgBcAAkAA8IEDQB+APgBeH0DaxH1mfQD6APhRvD4AfQB8YK8PQB8A7zZgGvc+sz4AfQD8KF4fgD4A3g4gjXuf2d8A9AHwo3h9APoA+MBeH4A+AD6wdxLQSUDeSUABIAB4ASAABAAfLwCMMfoAJCjP+wjgAfK8APAAeT5wALhPzfP6ABYnidyn5vnJ+eQ+Nc/H9cltKp6P65P71Dwf19sB8LwdwJIv96l5fvI+uU/N83F9cp+a5+N6JwF53klAD5DnBYAHyPPxAsAYow9AgvK8jwAeIM8LAA+Q5wMHgPvUPK8PYHGSyH1qnp+c1wfA84G924A8H9jrA+D5wN4OgOftAJZ8uU/N85P3+gB4PrDXB8Dzgb2TgDzvJKAHyPMCwAPk+XgBYIzRByBB+UH+6Oho8NTgfQSwAHgBIAAsAF4ACIDjL/ep+TX9qsV1eHiYt7e3By/gTfnI758+AL7YL1tYBwcHeWdn5+2llCELeJM+8vunD4Av9ssW1oULF/Le3t7gBbxJH/n9cxuQL/bLFtb+/v7bfw5dwJv0kd8/fQB8sT9pgQ1dwJv0kd8/OwD+THYAzQeAPoDkPjW/lp9kAOgDSO5T82v5SQaAPoDkPjW/lp9kAOgDcBKOdxLQUWALgBcAAsAC4AXARAPAGKMPwG9A3g7ARwALgBcAAsAC4AVA4ABwH57XB6APYHGSyH14vkcA6ANI+gD4GF4fQLvebUC+2OsDaNfrA+CLvT6Adr0dAH8mOwB9AK3vANyH5/UBTP790wfAF3t9AO16fQB8sdcH0K53EpB3EtBJQAuAFwACwALgBUC8ADDG6APwG5C3A/ARwALgBYAAsAB4ARA4ANyH5/UB6ANYnCRyH57vEQD6AJI+AD6G1wfQrncbkC/2+gDa9foA+GKvD6BdbwfAn8kOQB9A6zsA9+F5fQCTf//0AfDFXh9Au14fAF/s9QG0650E5J0EdBLQAuAFgACwAHgBEC8AjDH6APwG5O0AfASwAHgBIAAsAF4ABA4A9+F5fQD6ABYnidyH53sEgD6ApA+Aj+H1AbTr3Qbki70+gHa9PgC+2OsDaNfbAfBnsgPQB9D6DsB9eF4fwOTfP30AfLHXB9Cu1wfAF3t9AO16JwF5JwGdBLQAeAEgACwAXgDECwBjjD4AvwF5OwAfASwAXgAIAAuAFwCBA8B9eF4fgD6AxUki9+H5HgGgDyDpA+BjeH0A7Xq3Aflirw+gXa8PgC/2+gDa9XYA/JnsAPQBtL4DcB+e1wcw+fdPHwBf7PUBtOv1AfDFXh9Au95JQN5JQCcBLQBeAAgAC4AXAPECwBijD8BvQN4OwEcAC4AXAALAAuAFQOAAcB+e1wegD2Bxksh9eL5HAOgDSPoA+BheH0C73m1AvtjrA2jX6wPgi70+gHa9HQB/JjsAfQCt7wDch+f1AUz+/dMHwBd7fQDten0AfLHXB9CudxKQdxLQSUALgBcAAsAC4AVAqPfvPyVxz6xUBN7bAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 12345, + "texCoord" : 0, + "channels" : [ 0 ] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureInvalidType.gltf new file mode 100644 index 00000000..b25db0c6 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureInvalidType.gltf @@ -0,0 +1,123 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : "NOT_AN_OBJECT" + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureTexCoordInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureTexCoordInvalidType.gltf new file mode 100644 index 00000000..694ba1c1 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureTexCoordInvalidType.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : "NOT_A_NUMBER", + "channels" : [ 0 ] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureTexCoordInvalidValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureTexCoordInvalidValue.gltf new file mode 100644 index 00000000..ebcd977e --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/FeatureIdTextureTextureTexCoordInvalidValue.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : 12345, + "channels" : [ 0 ] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/README.md b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/README.md new file mode 100644 index 00000000..79230ba1 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/README.md @@ -0,0 +1,19 @@ + + +The files in this directory are used for the specs for the `EXT_mesh_features` +validation. + +The valid files have been taken from +https://github.com/CesiumGS/3d-tiles-samples/tree/a256d9f68df15bbfc75ea3891f52c72a36d04202/glTF/EXT_mesh_features + +The `ValidFeatureIdTexture.glb` and `ValidFeatureIdAttributeDefault/` are +intended for basic tests of binary- and default (non-embedded) glTF assets. + +The `ValidFeatureIdAttributeWithByteStride.glb` was created from the original +`ValidFeatureIdTexture.gltf` by passing it through https://gltf.report/ , which +happens to write all attributes in an interleaved way, causing a byte stride +to be inserted. + +The other files (starting with `FeatureIdTexture*` or `FeatureIdAttribute*`) +have been edited to cause validation errors (with the error indicated by +their file name, as far as reasonably possible). \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttribute.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttribute.gltf new file mode 100644 index 00000000..6941256b --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttribute.gltf @@ -0,0 +1,102 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeDefault/ValidFeatureIdAttributeDefault.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeDefault/ValidFeatureIdAttributeDefault.gltf new file mode 100644 index 00000000..aa475aa2 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeDefault/ValidFeatureIdAttributeDefault.gltf @@ -0,0 +1,159 @@ +{ + "extensionsUsed": [ + "EXT_mesh_features" + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 24, + "type": "SCALAR", + "max": [ + 15 + ], + "min": [ + 0 + ] + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 16, + "type": "VEC3", + "max": [ + 1, + 1, + 0 + ], + "min": [ + 0, + 0, + 0 + ] + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 16, + "type": "VEC3", + "max": [ + 0, + 0, + 1 + ], + "min": [ + 0, + 0, + 1 + ] + }, + { + "bufferView": 3, + "byteOffset": 0, + "componentType": 5121, + "count": 16, + "type": "SCALAR", + "max": [ + 3 + ], + "min": [ + 0 + ] + } + ], + "asset": { + "generator": "JglTF from https://github.com/javagl/JglTF", + "version": "2.0" + }, + "buffers": [ + { + "uri": "ValidFeatureIdAttributeDefault_data.bin", + "byteLength": 496 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 48, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 48, + "byteLength": 192, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 240, + "byteLength": 192, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 432, + "byteLength": 64, + "byteStride": 4, + "target": 34962 + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorFactor": [ + 0.5, + 1, + 0.5, + 1 + ], + "metallicFactor": 0, + "roughnessFactor": 1 + }, + "alphaMode": "OPAQUE", + "doubleSided": true + } + ], + "meshes": [ + { + "primitives": [ + { + "extensions": { + "EXT_mesh_features": { + "featureIds": [ + { + "featureCount": 4, + "attribute": 0 + } + ] + } + }, + "attributes": { + "POSITION": 1, + "NORMAL": 2, + "_FEATURE_ID_0": 3 + }, + "indices": 0, + "material": 0, + "mode": 4 + } + ] + } + ], + "nodes": [ + { + "mesh": 0 + } + ], + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeDefault/ValidFeatureIdAttributeDefault_data.bin b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeDefault/ValidFeatureIdAttributeDefault_data.bin new file mode 100644 index 00000000..244e011f Binary files /dev/null and b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeDefault/ValidFeatureIdAttributeDefault_data.bin differ diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeWithByteStride.glb b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeWithByteStride.glb new file mode 100644 index 00000000..1a0fd675 Binary files /dev/null and b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeWithByteStride.glb differ diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeWithLargerFeatureCount.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeWithLargerFeatureCount.gltf new file mode 100644 index 00000000..ed586fe5 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeWithLargerFeatureCount.gltf @@ -0,0 +1,102 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 123, + "attribute" : 0 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeWithNullFeatureId.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeWithNullFeatureId.gltf new file mode 100644 index 00000000..d68f4db3 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdAttributeWithNullFeatureId.gltf @@ -0,0 +1,103 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAA==", + "byteLength" : 496 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 3, + "attribute" : 0, + "nullFeatureId": 2 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdTexture.glb b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdTexture.glb new file mode 100644 index 00000000..3c6e8fb3 Binary files /dev/null and b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdTexture.glb differ diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdTexture.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdTexture.gltf new file mode 100644 index 00000000..4bcf87f5 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdTexture.gltf @@ -0,0 +1,127 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdTextureUsingDefaultChannels.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdTextureUsingDefaultChannels.gltf new file mode 100644 index 00000000..1d90d5d5 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/meshFeatures/ValidFeatureIdTextureUsingDefaultChannels.gltf @@ -0,0 +1,126 @@ +{ + "extensionsUsed" : [ "EXT_mesh_features" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAJElEQVR42mNgYmBgoAQzDLwBgwcwY8FDzIDBDRiR8KgBNDAAAOKBAKByX2jMAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "texture" : { + "index" : 1, + "texCoord" : 0 + } + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ExtensionInMeshPrimitiveWithoutTopLevelObject.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ExtensionInMeshPrimitiveWithoutTopLevelObject.gltf new file mode 100644 index 00000000..22abf652 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ExtensionInMeshPrimitiveWithoutTopLevelObject.gltf @@ -0,0 +1,275 @@ +{ + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyArray.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyArray.gltf new file mode 100644 index 00000000..7930ae0d --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyArray.gltf @@ -0,0 +1,328 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32", + "array": true + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyInvalidComponentType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyInvalidComponentType.gltf new file mode 100644 index 00000000..24824ea9 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyInvalidComponentType.gltf @@ -0,0 +1,327 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType": "FLOAT64" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyInvalidEnumValueType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyInvalidEnumValueType.gltf new file mode 100644 index 00000000..7be16026 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyInvalidEnumValueType.gltf @@ -0,0 +1,328 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType": "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "valueType": "INT64", + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyMaxNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyMaxNotInRange.gltf new file mode 100644 index 00000000..aefb928e --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyMaxNotInRange.gltf @@ -0,0 +1,339 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32", + "max": 0.7 + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + }, { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } + ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyMinNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyMinNotInRange.gltf new file mode 100644 index 00000000..3407dff7 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyMinNotInRange.gltf @@ -0,0 +1,339 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32", + "min": 0.3 + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + }, { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } + ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyString.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyString.gltf new file mode 100644 index 00000000..6020c709 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesClassPropertyString.gltf @@ -0,0 +1,326 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "STRING" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidElementType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidElementType.gltf new file mode 100644 index 00000000..ef983022 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidElementType.gltf @@ -0,0 +1,327 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0, "NOT_A_NUMBER" ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidElementValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidElementValue.gltf new file mode 100644 index 00000000..12c8fa0c --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidElementValue.gltf @@ -0,0 +1,327 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0, 12345 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidLength.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidLength.gltf new file mode 100644 index 00000000..3e12fb37 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidLength.gltf @@ -0,0 +1,327 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidType.gltf new file mode 100644 index 00000000..bccccf06 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesMeshPrimitivePropertyAttributesInvalidType.gltf @@ -0,0 +1,327 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : "NOT_A_NUMBER" + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyInvalidAttribute.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyInvalidAttribute.gltf new file mode 100644 index 00000000..920105f0 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyInvalidAttribute.gltf @@ -0,0 +1,327 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "THIS_ATTRIBUTE_DOES_NOT_EXIST" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMaxMismatch.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMaxMismatch.gltf new file mode 100644 index 00000000..28a56937 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMaxMismatch.gltf @@ -0,0 +1,339 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY", + "max": 0.3 + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + }, { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } + ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMaxNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMaxNotInRange.gltf new file mode 100644 index 00000000..c450bc0b --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMaxNotInRange.gltf @@ -0,0 +1,339 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY", + "max": 0.2 + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + }, { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } + ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMinMismatch.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMinMismatch.gltf new file mode 100644 index 00000000..db8f6f18 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMinMismatch.gltf @@ -0,0 +1,339 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY", + "min": 0.2 + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + }, { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } + ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMinNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMinNotInRange.gltf new file mode 100644 index 00000000..3b136e82 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyAttributesPropertyAttributePropertyMinNotInRange.gltf @@ -0,0 +1,339 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY", + "min": 0.3 + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + }, { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } + ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 1 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureClassPropertyMaxNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureClassPropertyMaxNotInRange.gltf new file mode 100644 index 00000000..19cf51eb --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureClassPropertyMaxNotInRange.gltf @@ -0,0 +1,171 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8", + "max": 23 + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAIvklEQVR42u3csW5URxsG4BHBRRoklxROEQlSRCJCKShoXFJZiDSpQEqX2pYii8ZVlDZF7oNcAAURDREdpCEXQKoIlAKFEE3O4s0KoV17zxm8Z+Z8j6zvj6Nfj7Q663k968y8aXd3NxtjYk6a/U9OafDwPN+uFwA8LwA8QJ4XAO/Mw26+6Garm6vd/NbzBfA8X79fGQCXuvll/v1P3XzZ8wXwPF+/X+sjwL/zJBm6BeF5vk6/VgC8nG8nhr4Anufr9GsFwA/d/FzwAnier9OfGgC/d/NdwV8heZ6v158YAH908203/wx8ATzP1+1XBsDsL4hfdfNq4H+H5Hm+fr8yAD6Z/Z/vTZ8XwPN8/d5JQJ53EtAD5HkB4AHyfLwAMMboA5CgPO8jgAfI8wLAA+R5fQDuU/O8PgD3qXleH4D71DyvD8B9ap7XB+A+Nc/rA+B5Xh8Az/P6AHie1wfA87w+AJ7nHQXmeV4A8DyvD8AYow+A53kfAXieFwA8z+sD4HleHwDP8/oAeJ7XB8DzvD4Anuf1AfA8rw+A53l9ADzP6wPgeV4fAM/zjgLzPC8AeJ7XB2CMOaEPIBV88TzfrhcAPC8APECeFwDvfj3p5lI3W91c7eZhzxfA83z1fnUA3O7mx/n333fzdc8XwPN89X51AHzazd/z7//s5vOeL4Dn+er96gD4+JR/P+0F8DxfvV8dAOm9f9/q+QJ4nq/e2wHwvB3Akq/Punk5//6v+V8U+7wAnuer96sD4Jv5Xw///yvi7Z4vgOf56v3qAPh1/pfEj+bp8aTnC+B5vnrvJCDPOwnoAfK8APAAeT5eABhj9AFIUJ73EcAD5HkB4AHyfOAAcJ+a5/UBLE4SuU/N85Pz+gB4PrB3G5DnA3t9ADwf2NsB8LwdwJIv96l5fvJeHwDPB/b6AHg+sHcSkOedBPQAeV4AeIA8Hy8AjDH6AMZLsJQHD+83IN/6RwABIAB4ASAABABfSwBs8j7zkh/sK1dyfvw459evc370KOfLl/stoFB+7PePb9bX0Qew5Af76dOcb906/v7OnePF0GcBhfJjv398s76OPoA1trqz34QlW+hJ+7HfP75ZX8dtwBN+8M+dy/nu3Zzv3Ru2gEL4sd8/vllfRx/Aih/+8+dzfvEi5zdvcr55s/8CCuPHfv/4Zn31O4DZ3LiR8/Pnw7fQk/d+A/IffAewyfvM/gbw4f8G4D4830wfwJIf7GfPjv9T2Oz769dzvn+/3wIK5cd+//hmfR19AEt+sK9dO/5PYbPffA8e5HzxYr8FFMqP/f7xzXonAZ0E5J0EFAACgBcAAkAA8PECwBijD8AOwA6A9xFAAAgAXgAIAAHABw4AfQD6AHh9AGkT95n1AegD4Efx+gD0AfCBvT4AfQC824Bp3PvM+gD0AfCjeH0A+gB4O4A07n1mfwPQB8CP4vUB6APgA3t9APoA+MDeSUAnAXknAQWAAOAFgAAQAHy8ADDG6AOwA7AD4H0EEAACgBcAAkAA8IEDQB+APgBeH0DaxH1mfQD6APhRvD4AfQB8YK8PQB8A7zZgGvc+sz4AfQD8KF4fgD4A3g4gjXuf2d8A9AHwo3h9APoA+MBeH4A+AD6wdxLQSUDeSUABIAB4ASAABAAfLwCMMfoAJCjP+wjgAfK8APAAeT5wALhPzfP6ABYnidyn5vnJ+eQ+Nc/H9cltKp6P65P71Dwf19sB8LwdwJIv96l5fvI+uU/N83F9cp+a5+N6JwF53klAD5DnBYAHyPPxAsAYow9AgvK8jwAeIM8LAA+Q5wMHgPvUPK8PYHGSyH1qnp+c1wfA84G924A8H9jrA+D5wN4OgOftAJZ8uU/N85P3+gB4PrDXB8Dzgb2TgDzvJKAHyPMCwAPk+XgBYIzRByBB+UH+6Oho8NTgfQSwAHgBIAAsAF4ACIDjL/ep+TX9qsV1eHiYt7e3By/gTfnI758+AL7YL1tYBwcHeWdn5+2llCELeJM+8vunD4Av9ssW1oULF/Le3t7gBbxJH/n9cxuQL/bLFtb+/v7bfw5dwJv0kd8/fQB8sT9pgQ1dwJv0kd8/OwD+THYAzQeAPoDkPjW/lp9kAOgDSO5T82v5SQaAPoDkPjW/lp9kAOgDcBKOdxLQUWALgBcAAsAC4AXARAPAGKMPwG9A3g7ARwALgBcAAsAC4AVA4ABwH57XB6APYHGSyH14vkcA6ANI+gD4GF4fQLvebUC+2OsDaNfrA+CLvT6Adr0dAH8mOwB9AK3vANyH5/UBTP790wfAF3t9AO16fQB8sdcH0K53EpB3EtBJQAuAFwACwALgBUC8ADDG6APwG5C3A/ARwALgBYAAsAB4ARA4ANyH5/UB6ANYnCRyH57vEQD6AJI+AD6G1wfQrncbkC/2+gDa9foA+GKvD6BdbwfAn8kOQB9A6zsA9+F5fQCTf//0AfDFXh9Au14fAF/s9QG0650E5J0EdBLQAuAFgACwAHgBEC8AjDH6APwG5O0AfASwAHgBIAAsAF4ABA4A9+F5fQD6ABYnidyH53sEgD6ApA+Aj+H1AbTr3Qbki70+gHa9PgC+2OsDaNfbAfBnsgPQB9D6DsB9eF4fwOTfP30AfLHXB9Cu1wfAF3t9AO16JwF5JwGdBLQAeAEgACwAXgDECwBjjD4AvwF5OwAfASwAXgAIAAuAFwCBA8B9eF4fgD6AxUki9+H5HgGgDyDpA+BjeH0A7Xq3Aflirw+gXa8PgC/2+gDa9XYA/JnsAPQBtL4DcB+e1wcw+fdPHwBf7PUBtOv1AfDFXh9Au95JQN5JQCcBLQBeAAgAC4AXAPECwBijD8BvQN4OwEcAC4AXAALAAuAFQOAAcB+e1wegD2Bxksh9eL5HAOgDSPoA+BheH0C73m1AvtjrA2jX6wPgi70+gHa9HQB/JjsAfQCt7wDch+f1AUz+/dMHwBd7fQDten0AfLHXB9CudxKQdxLQSUALgBcAAsAC4AVAqPfvPyVxz6xUBN7bAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureClassPropertyMinNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureClassPropertyMinNotInRange.gltf new file mode 100644 index 00000000..00f4a1ba --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureClassPropertyMinNotInRange.gltf @@ -0,0 +1,171 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8", + "min": 14 + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureClassPropertyWithOffsetScaleMinNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureClassPropertyWithOffsetScaleMinNotInRange.gltf new file mode 100644 index 00000000..920830cf --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureClassPropertyWithOffsetScaleMinNotInRange.gltf @@ -0,0 +1,173 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true, + "offset": 100.0, + "scale": 1000.0, + "min": 151 + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAIvklEQVR42u3csW5URxsG4BHBRRoklxROEQlSRCJCKShoXFJZiDSpQEqX2pYii8ZVlDZF7oNcAAURDREdpCEXQKoIlAKFEE3O4s0KoV17zxm8Z+Z8j6zvj6Nfj7Q663k968y8aXd3NxtjYk6a/U9OafDwPN+uFwA8LwA8QJ4XAO/Mw26+6Garm6vd/NbzBfA8X79fGQCXuvll/v1P3XzZ8wXwPF+/X+sjwL/zJBm6BeF5vk6/VgC8nG8nhr4Anufr9GsFwA/d/FzwAnier9OfGgC/d/NdwV8heZ6v158YAH908203/wx8ATzP1+1XBsDsL4hfdfNq4H+H5Hm+fr8yAD6Z/Z/vTZ8XwPN8/d5JQJ53EtAD5HkB4AHyfLwAMMboA5CgPO8jgAfI8wLAA+R5fQDuU/O8PgD3qXleH4D71DyvD8B9ap7XB+A+Nc/rA+B5Xh8Az/P6AHie1wfA87w+AJ7nHQXmeV4A8DyvD8AYow+A53kfAXieFwA8z+sD4HleHwDP8/oAeJ7XB8DzvD4Anuf1AfA8rw+A53l9ADzP6wPgeV4fAM/zjgLzPC8AeJ7XB2CMOaEPIBV88TzfrhcAPC8APECeFwDvfj3p5lI3W91c7eZhzxfA83z1fnUA3O7mx/n333fzdc8XwPN89X51AHzazd/z7//s5vOeL4Dn+er96gD4+JR/P+0F8DxfvV8dAOm9f9/q+QJ4nq/e2wHwvB3Akq/Punk5//6v+V8U+7wAnuer96sD4Jv5Xw///yvi7Z4vgOf56v3qAPh1/pfEj+bp8aTnC+B5vnrvJCDPOwnoAfK8APAAeT5eABhj9AFIUJ73EcAD5HkB4AHyfOAAcJ+a5/UBLE4SuU/N85Pz+gB4PrB3G5DnA3t9ADwf2NsB8LwdwJIv96l5fvJeHwDPB/b6AHg+sHcSkOedBPQAeV4AeIA8Hy8AjDH6AMZLsJQHD+83IN/6RwABIAB4ASAABABfSwBs8j7zkh/sK1dyfvw459evc370KOfLl/stoFB+7PePb9bX0Qew5Af76dOcb906/v7OnePF0GcBhfJjv398s76OPoA1trqz34QlW+hJ+7HfP75ZX8dtwBN+8M+dy/nu3Zzv3Ru2gEL4sd8/vllfRx/Aih/+8+dzfvEi5zdvcr55s/8CCuPHfv/4Zn31O4DZ3LiR8/Pnw7fQk/d+A/IffAewyfvM/gbw4f8G4D4830wfwJIf7GfPjv9T2Oz769dzvn+/3wIK5cd+//hmfR19AEt+sK9dO/5PYbPffA8e5HzxYr8FFMqP/f7xzXonAZ0E5J0EFAACgBcAAkAA8PECwBijD8AOwA6A9xFAAAgAXgAIAAHABw4AfQD6AHh9AGkT95n1AegD4Efx+gD0AfCBvT4AfQC824Bp3PvM+gD0AfCjeH0A+gB4O4A07n1mfwPQB8CP4vUB6APgA3t9APoA+MDeSUAnAXknAQWAAOAFgAAQAHy8ADDG6AOwA7AD4H0EEAACgBcAAkAA8IEDQB+APgBeH0DaxH1mfQD6APhRvD4AfQB8YK8PQB8A7zZgGvc+sz4AfQD8KF4fgD4A3g4gjXuf2d8A9AHwo3h9APoA+MBeH4A+AD6wdxLQSUDeSUABIAB4ASAABAAfLwCMMfoAJCjP+wjgAfK8APAAeT5wALhPzfP6ABYnidyn5vnJ+eQ+Nc/H9cltKp6P65P71Dwf19sB8LwdwJIv96l5fvI+uU/N83F9cp+a5+N6JwF53klAD5DnBYAHyPPxAsAYow9AgvK8jwAeIM8LAA+Q5wMHgPvUPK8PYHGSyH1qnp+c1wfA84G924A8H9jrA+D5wN4OgOftAJZ8uU/N85P3+gB4PrDXB8Dzgb2TgDzvJKAHyPMCwAPk+XgBYIzRByBB+UH+6Oho8NTgfQSwAHgBIAAsAF4ACIDjL/ep+TX9qsV1eHiYt7e3By/gTfnI758+AL7YL1tYBwcHeWdn5+2llCELeJM+8vunD4Av9ssW1oULF/Le3t7gBbxJH/n9cxuQL/bLFtb+/v7bfw5dwJv0kd8/fQB8sT9pgQ1dwJv0kd8/OwD+THYAzQeAPoDkPjW/lp9kAOgDSO5T82v5SQaAPoDkPjW/lp9kAOgDcBKOdxLQUWALgBcAAsAC4AXARAPAGKMPwG9A3g7ARwALgBcAAsAC4AVA4ABwH57XB6APYHGSyH14vkcA6ANI+gD4GF4fQLvebUC+2OsDaNfrA+CLvT6Adr0dAH8mOwB9AK3vANyH5/UBTP790wfAF3t9AO16fQB8sdcH0K53EpB3EtBJQAuAFwACwALgBUC8ADDG6APwG5C3A/ARwALgBYAAsAB4ARA4ANyH5/UB6ANYnCRyH57vEQD6AJI+AD6G1wfQrncbkC/2+gDa9foA+GKvD6BdbwfAn8kOQB9A6zsA9+F5fQCTf//0AfDFXh9Au14fAF/s9QG0650E5J0EdBLQAuAFgACwAHgBEC8AjDH6APwG5O0AfASwAHgBIAAsAF4ABA4A9+F5fQD6ABYnidyH53sEgD6ApA+Aj+H1AbTr3Qbki70+gHa9PgC+2OsDaNfbAfBnsgPQB9D6DsB9eF4fwOTfP30AfLHXB9Cu1wfAF3t9AO16JwF5JwGdBLQAeAEgACwAXgDECwBjjD4AvwF5OwAfASwAXgAIAAuAFwCBA8B9eF4fgD6AxUki9+H5HgGgDyDpA+BjeH0A7Xq3Aflirw+gXa8PgC/2+gDa9XYA/JnsAPQBtL4DcB+e1wcw+fdPHwBf7PUBtOv1AfDFXh9Au95JQN5JQCcBLQBeAAgAC4AXAPECwBijD8BvQN4OwEcAC4AXAALAAuAFQOAAcB+e1wegD2Bxksh9eL5HAOgDSPoA+BheH0C73m1AvtjrA2jX6wPgi70+gHa9HQB/JjsAfQCt7wDch+f1AUz+/dMHwBd7fQDten0AfLHXB9CudxKQdxLQSUALgBcAAsAC4AVAqPfvPyVxz6xUBN7bAAAAAElFTkSuQmCC", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureEnumsInvalidEnumValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureEnumsInvalidEnumValue.gltf new file mode 100644 index 00000000..6cd34c43 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureEnumsInvalidEnumValue.gltf @@ -0,0 +1,176 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "PropertyTextureEnumsSchemaId", + "classes" : { + "propertyTextureEnumsClass" : { + "name" : "Property texture example enum properties", + "properties" : { + "enumProperty" : { + "name" : "Example enum property", + "type" : "ENUM", + "enumType" : "exampleEnum", + "noData" : "NO_DATA_ENUM_VALUE", + "default" : "DEFAULT_ENUM_VALUE" + }, + "enumArrayProperty" : { + "name" : "Example enum array property", + "type" : "ENUM", + "enumType" : "exampleEnum", + "array" : true, + "count" : 2, + "noData" : [ "NO_DATA_ENUM_VALUE", "NO_DATA_ENUM_VALUE" ], + "default" : [ "DEFAULT_ENUM_VALUE", "DEFAULT_ENUM_VALUE" ] + } + } + } + }, + "enums" : { + "exampleEnum" : { + "valueType": "UINT8", + "values" : [ { + "name" : "NO_DATA_ENUM_VALUE", + "value" : 255 + }, { + "name" : "EXAMPLE_ENUM_VALUE_A", + "value" : 0 + }, { + "name" : "EXAMPLE_ENUM_VALUE_B", + "value" : 1 + }, { + "name" : "EXAMPLE_ENUM_VALUE_C", + "value" : 2 + }, { + "name" : "DEFAULT_ENUM_VALUE", + "value" : 3 + } ] + } + } + }, + "propertyTextures" : [ { + "class" : "propertyTextureEnumsClass", + "properties" : { + "enumProperty" : { + "index" : 0, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "enumArrayProperty" : { + "index" : 0, + "texCoord" : 0, + "channels" : [ 1, 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAGUlEQVR42mP4/5/hPwMTAwNDSgpDCpBmAgA21QQw4gn1GgAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 0.5, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureInvalidPropertyTypeA.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureInvalidPropertyTypeA.gltf new file mode 100644 index 00000000..089ecac1 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureInvalidPropertyTypeA.gltf @@ -0,0 +1,169 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "STRING" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureInvalidPropertyTypeB.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureInvalidPropertyTypeB.gltf new file mode 100644 index 00000000..7f20406e --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureInvalidPropertyTypeB.gltf @@ -0,0 +1,171 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8", + "array": true + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTextureTexCoordInvalidValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTextureTexCoordInvalidValue.gltf new file mode 100644 index 00000000..35878937 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTextureTexCoordInvalidValue.gltf @@ -0,0 +1,170 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 12345, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidElementType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidElementType.gltf new file mode 100644 index 00000000..266bc3ca --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidElementType.gltf @@ -0,0 +1,170 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [0, "NOT_A_NUMBER"] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidElementValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidElementValue.gltf new file mode 100644 index 00000000..e28325b9 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidElementValue.gltf @@ -0,0 +1,170 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [0, 12345] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidLength.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidLength.gltf new file mode 100644 index 00000000..3f7034f4 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidLength.gltf @@ -0,0 +1,170 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidType.gltf new file mode 100644 index 00000000..3a3aa63e --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTextureMeshPrimitivePropertyTexturesInvalidType.gltf @@ -0,0 +1,170 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : "NOT_AN_ARRAY" + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyChannelsSizeMismatch.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyChannelsSizeMismatch.gltf new file mode 100644 index 00000000..b2fadc0d --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyChannelsSizeMismatch.gltf @@ -0,0 +1,170 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT16", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyIndexInvalidType.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyIndexInvalidType.gltf new file mode 100644 index 00000000..206d687e --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyIndexInvalidType.gltf @@ -0,0 +1,170 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : "NOT_A_NUMBER", + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyIndexInvalidValue.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyIndexInvalidValue.gltf new file mode 100644 index 00000000..adc5e5b2 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyIndexInvalidValue.gltf @@ -0,0 +1,170 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 12345, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMaxMismatch.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMaxMismatch.gltf new file mode 100644 index 00000000..4d692aeb --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMaxMismatch.gltf @@ -0,0 +1,171 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ], + "max": 29 + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMaxNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMaxNotInRange.gltf new file mode 100644 index 00000000..14646845 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMaxNotInRange.gltf @@ -0,0 +1,171 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ], + "max": 23 + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMinMismatch.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMinMismatch.gltf new file mode 100644 index 00000000..e294d990 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMinMismatch.gltf @@ -0,0 +1,171 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ], + "min": 9 + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMinNotInRange.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMinNotInRange.gltf new file mode 100644 index 00000000..62555c3d --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/PropertyTexturePropertyTexturePropertyMinNotInRange.gltf @@ -0,0 +1,171 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ], + "min": 14 + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/README.md b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/README.md new file mode 100644 index 00000000..a35374cb --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/README.md @@ -0,0 +1,21 @@ +The files in this directory are used for the specs for the +`EXT_structural_metadata` validation. + +The valid files have been taken from +https://github.com/CesiumGS/3d-tiles-samples/tree/a256d9f68df15bbfc75ea3891f52c72a36d04202/glTF/EXT_structural_metadata +except for the following ones, which have been created dedicatedly for these tests: + +- `ValidPropertyAttributes.gltf` +- `ValidPropertyTextureEnums.gltf` + +The files that cause issues have been created by modifying these files +This mostly happened manually, with the exception of certain invalid values in +property textures, that have been written out in this form by the generator. + +Note that some parts of the validation specs are not covered here, because +they are covered by the main 3D Tiles Validator specs. Particularly: + +- Validation of the metadata schema is covered with `./specs/data/schemas/` +- Validation of the property tables is covered with `./specs/data/subtrees/subtreePropertyTables*.json` + + diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/StructuralMetadataMissingSchema.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/StructuralMetadataMissingSchema.gltf new file mode 100644 index 00000000..aeffde30 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/StructuralMetadataMissingSchema.gltf @@ -0,0 +1,173 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "propertyTables" : [ { + "name" : "First example property table", + "class" : "exampleMetadataClassA", + "count" : 4, + "properties" : { + "example_FLOAT32" : { + "values" : 5 + }, + "example_INT64" : { + "values" : 6 + } + } + }, { + "name" : "Second example property table", + "class" : "exampleMetadataClassB", + "count" : 4, + "properties" : { + "example_UINT16" : { + "values" : 7 + }, + "example_FLOAT64" : { + "values" : 8 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_mesh_features", "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AwAAAAMAAAADAAAAAwAAAAIAAAACAAAAAgAAAAIAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAACAAAAAgAAAAIAAAACAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA=", + "byteLength" : 560 + }, { + "uri" : "data:application/gltf-buffer;base64,zcyMP83MDEAzM1NAzcyMQIfWEgAAAAAAzsojAAAAAAAVvzQAAAAAAFKzRQAAAAAA", + "byteLength" : 48 + }, { + "uri" : "data:application/gltf-buffer;base64,OTCgWweHbrKHiJtTycDzP9GSx9PywwJAX2HB/YCnC0Da5sb0hEUSQA==", + "byteLength" : 40 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 496, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 16 + }, { + "buffer" : 1, + "byteOffset" : 16, + "byteLength" : 32 + }, { + "buffer" : 2, + "byteOffset" : 0, + "byteLength" : 8 + }, { + "buffer" : 2, + "byteOffset" : 8, + "byteLength" : 32 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0, + "propertyTable" : 0 + }, { + "featureCount" : 4, + "attribute" : 1, + "propertyTable" : 1 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3, + "_FEATURE_ID_1" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/StructuralMetadataSchemaAndSchemaUri.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/StructuralMetadataSchemaAndSchemaUri.gltf new file mode 100644 index 00000000..dfdff5d6 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/StructuralMetadataSchemaAndSchemaUri.gltf @@ -0,0 +1,229 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schemaUri": "uriToCreateValidationError.json", + "schema" : { + "id": "MultipleClassesSchema", + "classes" : { + "exampleMetadataClassA" : { + "name" : "Example metadata class A", + "description" : "First example metadata class", + "properties" : { + "example_FLOAT32" : { + "name" : "Example FLOAT32 property", + "description" : "An example property, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "example_INT64" : { + "name" : "Example INT64 property", + "description" : "An example property, with component type INT64", + "type" : "SCALAR", + "componentType" : "INT64" + } + } + }, + "exampleMetadataClassB" : { + "name" : "Example metadata class B", + "description" : "Second example metadata class", + "properties" : { + "example_UINT16" : { + "name" : "Example UINT16 property", + "description" : "An example property, with component type UINT16", + "type" : "SCALAR", + "componentType" : "UINT16" + }, + "example_FLOAT64" : { + "name" : "Example FLOAT64 property", + "description" : "An example property, with component type FLOAT64", + "type" : "SCALAR", + "componentType" : "FLOAT64" + } + } + } + }, + "enums" : { + "exampleEnumType" : { + "values" : [ { + "name" : "ExampleEnumValueA", + "value" : 0 + }, { + "name" : "ExampleEnumValueB", + "value" : 1 + }, { + "name" : "ExampleEnumValueC", + "value" : 2 + } ] + } + } + }, + "propertyTables" : [ { + "name" : "First example property table", + "class" : "exampleMetadataClassA", + "count" : 4, + "properties" : { + "example_FLOAT32" : { + "values" : 5 + }, + "example_INT64" : { + "values" : 6 + } + } + }, { + "name" : "Second example property table", + "class" : "exampleMetadataClassB", + "count" : 4, + "properties" : { + "example_UINT16" : { + "values" : 7 + }, + "example_FLOAT64" : { + "values" : 8 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_mesh_features", "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AwAAAAMAAAADAAAAAwAAAAIAAAACAAAAAgAAAAIAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAACAAAAAgAAAAIAAAACAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA=", + "byteLength" : 560 + }, { + "uri" : "data:application/gltf-buffer;base64,zcyMP83MDEAzM1NAzcyMQIfWEgAAAAAAzsojAAAAAAAVvzQAAAAAAFKzRQAAAAAA", + "byteLength" : 48 + }, { + "uri" : "data:application/gltf-buffer;base64,OTCgWweHbrKHiJtTycDzP9GSx9PywwJAX2HB/YCnC0Da5sb0hEUSQA==", + "byteLength" : 40 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 496, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 16 + }, { + "buffer" : 1, + "byteOffset" : 16, + "byteLength" : 32 + }, { + "buffer" : 2, + "byteOffset" : 0, + "byteLength" : 8 + }, { + "buffer" : 2, + "byteOffset" : 8, + "byteLength" : 32 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0, + "propertyTable" : 0 + }, { + "featureCount" : 4, + "attribute" : 1, + "propertyTable" : 1 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3, + "_FEATURE_ID_1" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidMultipleClasses.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidMultipleClasses.gltf new file mode 100644 index 00000000..c91427b9 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidMultipleClasses.gltf @@ -0,0 +1,228 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "MultipleClassesSchema", + "classes" : { + "exampleMetadataClassA" : { + "name" : "Example metadata class A", + "description" : "First example metadata class", + "properties" : { + "example_FLOAT32" : { + "name" : "Example FLOAT32 property", + "description" : "An example property, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "example_INT64" : { + "name" : "Example INT64 property", + "description" : "An example property, with component type INT64", + "type" : "SCALAR", + "componentType" : "INT64" + } + } + }, + "exampleMetadataClassB" : { + "name" : "Example metadata class B", + "description" : "Second example metadata class", + "properties" : { + "example_UINT16" : { + "name" : "Example UINT16 property", + "description" : "An example property, with component type UINT16", + "type" : "SCALAR", + "componentType" : "UINT16" + }, + "example_FLOAT64" : { + "name" : "Example FLOAT64 property", + "description" : "An example property, with component type FLOAT64", + "type" : "SCALAR", + "componentType" : "FLOAT64" + } + } + } + }, + "enums" : { + "exampleEnumType" : { + "values" : [ { + "name" : "ExampleEnumValueA", + "value" : 0 + }, { + "name" : "ExampleEnumValueB", + "value" : 1 + }, { + "name" : "ExampleEnumValueC", + "value" : 2 + } ] + } + } + }, + "propertyTables" : [ { + "name" : "First example property table", + "class" : "exampleMetadataClassA", + "count" : 4, + "properties" : { + "example_FLOAT32" : { + "values" : 5 + }, + "example_INT64" : { + "values" : 6 + } + } + }, { + "name" : "Second example property table", + "class" : "exampleMetadataClassB", + "count" : 4, + "properties" : { + "example_UINT16" : { + "values" : 7 + }, + "example_FLOAT64" : { + "values" : 8 + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_mesh_features", "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 24, + "type" : "SCALAR", + "max" : [ 15 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 16, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5121, + "count" : 16, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIABAAFAAYABQAHAAYACAAJAAoACQALAAoADAANAA4ADQAPAA4AAAAAAAAAAAAAAAAAZmbmPgAAAAAAAAAAAAAAAGZm5j4AAAAAZmbmPmZm5j4AAAAAzcwMPwAAAAAAAAAAAACAPwAAAAAAAAAAzcwMP2Zm5j4AAAAAAACAP2Zm5j4AAAAAAAAAAM3MDD8AAAAAZmbmPs3MDD8AAAAAAAAAAAAAgD8AAAAAZmbmPgAAgD8AAAAAzcwMP83MDD8AAAAAAACAP83MDD8AAAAAzcwMPwAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AwAAAAMAAAADAAAAAwAAAAIAAAACAAAAAgAAAAIAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAADAAAAAwAAAAMAAAACAAAAAgAAAAIAAAACAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAA=", + "byteLength" : 560 + }, { + "uri" : "data:application/gltf-buffer;base64,zcyMP83MDEAzM1NAzcyMQIfWEgAAAAAAzsojAAAAAAAVvzQAAAAAAFKzRQAAAAAA", + "byteLength" : 48 + }, { + "uri" : "data:application/gltf-buffer;base64,OTCgWweHbrKHiJtTycDzP9GSx9PywwJAX2HB/YCnC0Da5sb0hEUSQA==", + "byteLength" : 40 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 48, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 48, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 240, + "byteLength" : 192, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 432, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 496, + "byteLength" : 64, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 1, + "byteOffset" : 0, + "byteLength" : 16 + }, { + "buffer" : 1, + "byteOffset" : 16, + "byteLength" : 32 + }, { + "buffer" : 2, + "byteOffset" : 0, + "byteLength" : 8 + }, { + "buffer" : 2, + "byteOffset" : 8, + "byteLength" : 32 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 1.0, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_mesh_features" : { + "featureIds" : [ { + "featureCount" : 4, + "attribute" : 0, + "propertyTable" : 0 + }, { + "featureCount" : 4, + "attribute" : 1, + "propertyTable" : 1 + } ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_FEATURE_ID_0" : 3, + "_FEATURE_ID_1" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidPropertyAttributes.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidPropertyAttributes.gltf new file mode 100644 index 00000000..6ce7d2f7 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidPropertyAttributes.gltf @@ -0,0 +1,327 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyAttributeSchema", + "classes" : { + "exampleMetadataClass" : { + "name" : "Example metadata class", + "description" : "An example metadata class for property attributes", + "properties" : { + "intensity" : { + "name" : "Example intensity property", + "description" : "An example property for the intensity, with component type FLOAT32", + "type" : "SCALAR", + "componentType" : "FLOAT32" + }, + "classification" : { + "name" : "Example classification property", + "description" : "An example property for the classification, with the classificationEnumType", + "type" : "ENUM", + "enumType" : "classificationEnumType" + } + } + } + }, + "enums" : { + "classificationEnumType" : { + "values" : [ { + "name" : "ExampleClassificationA", + "value" : 0 + }, { + "name" : "ExampleClassificationB", + "value" : 1 + }, { + "name" : "ExampleClassificationC", + "value" : 2 + } ] + } + } + }, + "propertyAttributes" : [ { + "class" : "exampleMetadataClass", + "properties" : { + "intensity" : { + "attribute" : "_INTENSITY" + }, + "classification" : { + "attribute" : "_CLASSIFICATION" + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 1.0, 0.0 ], + "min" : [ -1.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.25 ], + "min" : [ 0.25 ] + }, { + "bufferView" : 4, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0 ], + "min" : [ 0 ] + }, { + "bufferView" : 5, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 6, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 7, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 8, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.5 ], + "min" : [ 0.5 ] + }, { + "bufferView" : 9, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 1 ], + "min" : [ 1 ] + }, { + "bufferView" : 10, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 11, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 2.0, 1.0, 0.0 ], + "min" : [ 1.0, 0.0, 0.0 ] + }, { + "bufferView" : 12, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 13, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "SCALAR", + "max" : [ 0.75 ], + "min" : [ 0.75 ] + }, { + "bufferView" : 14, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 4, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 2 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAACAvwAAAAAAAAAAAAAAAAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPgAAgD4AAIA+AACAPgAAAAAAAAAAAAAAAAAAAAAAAAEAAgABAAMAAgAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAIA/AACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAA/AAAAPwAAAD8AAAA/AQAAAAEAAAABAAAAAQAAAAAAAQACAAEAAwACAAAAgD8AAAAAAAAAAAAAAEAAAAAAAAAAAAAAgD8AAIA/AAAAAAAAAEAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAQD8AAEA/AABAPwAAQD8CAAAAAgAAAAIAAAACAAAA", + "byteLength" : 420 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 124, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 140, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 152, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 200, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 248, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 264, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 280, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 292, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 340, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 388, + "byteLength" : 16, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 404, + "byteLength" : 16, + "byteStride" : 4, + "target" : 34962 + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "_INTENSITY" : 3, + "_CLASSIFICATION" : 4 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 6, + "NORMAL" : 7, + "_INTENSITY" : 8, + "_CLASSIFICATION" : 9 + }, + "indices" : 5, + "material" : 0, + "mode" : 4 + }, { + "extensions" : { + "EXT_structural_metadata" : { + "propertyAttributes" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "_INTENSITY" : 13, + "_CLASSIFICATION" : 14 + }, + "indices" : 10, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidPropertyTexture.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidPropertyTexture.gltf new file mode 100644 index 00000000..6319b899 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidPropertyTexture.gltf @@ -0,0 +1,170 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "SimplePropertyTextureSchema", + "classes" : { + "buildingComponents" : { + "name" : "Building properties", + "properties" : { + "insideTemperature" : { + "name" : "Inside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "outsideTemperature" : { + "name" : "Outside Temperature", + "type" : "SCALAR", + "componentType" : "UINT8" + }, + "insulation" : { + "name" : "Insulation Thickness", + "type" : "SCALAR", + "componentType" : "UINT8", + "normalized" : true + } + } + } + } + }, + "propertyTextures" : [ { + "class" : "buildingComponents", + "properties" : { + "insideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "outsideTemperature" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 1 ] + }, + "insulation" : { + "index" : 1, + "texCoord" : 0, + "channels" : [ 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,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", + "mimeType" : "image/png" + }, { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABLUlEQVR42mVSSxbDIAh0GzUxKZrmCF3n/oerIx9pupgHIswAGtblE7bIKN0vqSOyXSOjPLAtktv9sCFxmcXj7EgsFj8zN00yYxrBZZJBRYk2LdC4WCDUfAdab7bpDm1lCyBW+7lpDnyNS34gcTQRltTPbAeEdFjcSQ0X9EOhGPYjhgLA7xh3kjxEEpMj1qQj7iAzAYoPELzYtuwK02M06WywAFDfX1MdJEoOtSZ7Allz1mYmWZDNL0pNF6ezu9jsQJUcNK7qzbWvMdSYQ8Jo7KKK8/uo4dxreHe0/HgF2/IqBen/za+Di69Sf8cZz5jmk+hcuhdd2tWLz8IE5MbFnRWT+yyU5vZJRtAOqlvq6MDeOrstu0UidsoO0Ak9xGwE+67+34salNEBSCxX7Bexg0rbq6TFvwAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 1.0, 1.0, 1.0, 1.0 ], + "baseColorTexture" : { + "index" : 0, + "texCoord" : 0 + }, + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + }, { + "sampler" : 0, + "source" : 1 + } ] +} \ No newline at end of file diff --git a/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidPropertyTextureEnums.gltf b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidPropertyTextureEnums.gltf new file mode 100644 index 00000000..38db37e2 --- /dev/null +++ b/tests/SharpGLTF.Cesium.Tests/testfixtures/structuralMetadata/ValidPropertyTextureEnums.gltf @@ -0,0 +1,176 @@ +{ + "extensions" : { + "EXT_structural_metadata" : { + "schema" : { + "id": "PropertyTextureEnumsSchemaId", + "classes" : { + "propertyTextureEnumsClass" : { + "name" : "Property texture example enum properties", + "properties" : { + "enumProperty" : { + "name" : "Example enum property", + "type" : "ENUM", + "enumType" : "exampleEnum", + "noData" : "NO_DATA_ENUM_VALUE", + "default" : "DEFAULT_ENUM_VALUE" + }, + "enumArrayProperty" : { + "name" : "Example enum array property", + "type" : "ENUM", + "enumType" : "exampleEnum", + "array" : true, + "count" : 2, + "noData" : [ "NO_DATA_ENUM_VALUE", "NO_DATA_ENUM_VALUE" ], + "default" : [ "DEFAULT_ENUM_VALUE", "DEFAULT_ENUM_VALUE" ] + } + } + } + }, + "enums" : { + "exampleEnum" : { + "valueType": "UINT8", + "values" : [ { + "name" : "NO_DATA_ENUM_VALUE", + "value" : 255 + }, { + "name" : "EXAMPLE_ENUM_VALUE_A", + "value" : 0 + }, { + "name" : "EXAMPLE_ENUM_VALUE_B", + "value" : 1 + }, { + "name" : "EXAMPLE_ENUM_VALUE_C", + "value" : 2 + }, { + "name" : "DEFAULT_ENUM_VALUE", + "value" : 3 + } ] + } + } + }, + "propertyTextures" : [ { + "class" : "propertyTextureEnumsClass", + "properties" : { + "enumProperty" : { + "index" : 0, + "texCoord" : 0, + "channels" : [ 0 ] + }, + "enumArrayProperty" : { + "index" : 0, + "texCoord" : 0, + "channels" : [ 1, 2 ] + } + } + } ] + } + }, + "extensionsUsed" : [ "EXT_structural_metadata" ], + "accessors" : [ { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 6, + "type" : "SCALAR", + "max" : [ 3 ], + "min" : [ 0 ] + }, { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + }, { + "bufferView" : 2, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC3", + "max" : [ 0.0, 0.0, 1.0 ], + "min" : [ 0.0, 0.0, 1.0 ] + }, { + "bufferView" : 3, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 4, + "type" : "VEC2", + "max" : [ 1.0, 1.0 ], + "min" : [ 0.0, 0.0 ] + } ], + "asset" : { + "generator" : "JglTF from https://github.com/javagl/JglTF", + "version" : "2.0" + }, + "buffers" : [ { + "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 140 + } ], + "bufferViews" : [ { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 12, + "target" : 34963 + }, { + "buffer" : 0, + "byteOffset" : 12, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 60, + "byteLength" : 48, + "target" : 34962 + }, { + "buffer" : 0, + "byteOffset" : 108, + "byteLength" : 32, + "target" : 34962 + } ], + "images" : [ { + "uri" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAGUlEQVR42mP4/5/hPwMTAwMDIyMDI5BmAgAvGQMH5R702wAAAABJRU5ErkJggg==", + "mimeType" : "image/png" + } ], + "materials" : [ { + "pbrMetallicRoughness" : { + "baseColorFactor" : [ 0.5, 0.5, 0.5, 1.0 ], + "metallicFactor" : 0.0, + "roughnessFactor" : 1.0 + }, + "alphaMode" : "OPAQUE", + "doubleSided" : true + } ], + "meshes" : [ { + "primitives" : [ { + "extensions" : { + "EXT_structural_metadata" : { + "propertyTextures" : [ 0 ] + } + }, + "attributes" : { + "POSITION" : 1, + "NORMAL" : 2, + "TEXCOORD_0" : 3 + }, + "indices" : 0, + "material" : 0, + "mode" : 4 + } ] + } ], + "nodes" : [ { + "mesh" : 0 + } ], + "samplers" : [ { + "magFilter" : 9728, + "minFilter" : 9728 + } ], + "scene" : 0, + "scenes" : [ { + "nodes" : [ 0 ] + } ], + "textures" : [ { + "sampler" : 0, + "source" : 0 + } ] +} \ No newline at end of file