| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.Linq;
- using SharpGLTF.Collections;
- using SharpGLTF.Validation;
- namespace SharpGLTF.Schema2
- {
- using Tiles3D;
- partial class Tiles3DExtensions
- {
- internal static void ValidateFeatureIdReferences(this IMeshFeatureIDInfo featureId, ModelRoot root)
- {
- if (featureId.PropertyTable.HasValue)
- {
- var metadataExtension = root.GetExtension<EXTStructuralMetadataRoot>();
- Guard.NotNull(metadataExtension, nameof(metadataExtension), "EXT_Structural_Metadata extension is not found.");
- Guard.NotNull(metadataExtension.PropertyTables[featureId.PropertyTable.Value], nameof(featureId.PropertyTable), $"Property table index {featureId.PropertyTable.Value} does not exist");
- }
- }
- internal static void ValidateFeatureIdContent(this IMeshFeatureIDInfo featureId)
- {
- Guard.MustBeGreaterThanOrEqualTo((int)featureId.FeatureCount, 1, nameof(featureId.FeatureCount));
- if (featureId.NullFeatureId.HasValue)
- {
- Guard.MustBeGreaterThanOrEqualTo((int)featureId.NullFeatureId, 0, nameof(featureId.NullFeatureId));
- }
- if (featureId.Label != null)
- {
- 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));
- }
- if (featureId.PropertyTable.HasValue)
- {
- Guard.MustBeGreaterThanOrEqualTo((int)featureId.PropertyTable, 0, nameof(featureId.PropertyTable));
- }
- }
- /// <summary>
- /// Set the FeatureIds for a MeshPrimitive
- /// </summary>
- public static MeshExtInstanceFeatureID[] SetInstanceFeatureIds(this Node node, params IMeshFeatureIDInfo[] featureIds)
- {
- if (featureIds == null || featureIds.Length == 0) { node.RemoveExtensions<MeshExtInstanceFeatures>(); return Array.Empty<MeshExtInstanceFeatureID>(); }
- var ext = node.UseExtension<MeshExtInstanceFeatures>();
- var result = new MeshExtInstanceFeatureID[featureIds.Length];
- for (int i = 0; i < result.Length; ++i)
- {
- result[i] = ext.CreateFeatureID(featureIds[i]);
- }
- return result;
- }
- /// <summary>
- /// Set the FeatureIds for a MeshPrimitive
- /// </summary>
- public static MeshExtMeshFeatureID[] SetMeshFeatureIds(this MeshPrimitive primitive, params (IMeshFeatureIDInfo fid, Texture tex, IReadOnlyList<int> channels)[] featureIds)
- {
- if (featureIds == null || featureIds.Length == 0) { primitive.RemoveExtensions<MeshExtMeshFeatures>(); return Array.Empty<MeshExtMeshFeatureID>(); }
- var ext = primitive.UseExtension<MeshExtMeshFeatures>();
- var result = new MeshExtMeshFeatureID[featureIds.Length];
- for (int i = 0; i < result.Length; ++i)
- {
- var (fid, tex, channels) = featureIds[i];
- result[i] = ext.CreateFeatureID(fid, tex, channels);
- }
- return result;
- }
- }
- namespace Tiles3D
- {
- /// <remarks>
- /// This extension is attached to a <see cref="Schema2.Node"/> using <see cref="ExtraProperties.UseExtension{T}"/>
- /// </remarks>
- public partial class MeshExtInstanceFeatures
- {
- #region lifecycle
- internal MeshExtInstanceFeatures() { }
- internal MeshExtInstanceFeatures(Node node)
- {
- _node = node;
- _featureIds = new ChildrenList<MeshExtInstanceFeatureID, MeshExtInstanceFeatures>(this);
- }
- protected override IEnumerable<ExtraProperties> GetLogicalChildren()
- {
- return base.GetLogicalChildren().Concat(_featureIds);
- }
- #endregion
- #region data
- private Node _node;
- #endregion
- #region properties
- public Node LogicalParent => _node;
- public IReadOnlyList<MeshExtInstanceFeatureID> FeatureIds => _featureIds;
- #endregion
- #region API
- public MeshExtInstanceFeatureID CreateFeatureID(IMeshFeatureIDInfo properties)
- {
- var instance = CreateFeatureID();
- instance.FeatureCount = properties.FeatureCount;
- instance.NullFeatureId = properties.NullFeatureId;
- instance.Label = properties.Label;
- instance.Attribute = properties.Attribute;
- instance.PropertyTable = properties.PropertyTable;
- return instance;
- }
- public MeshExtInstanceFeatureID CreateFeatureID()
- {
- var featureId = new MeshExtInstanceFeatureID();
- _featureIds.Add(featureId);
- return featureId;
- }
- #endregion
- #region validation
- protected override void OnValidateReferences(ValidationContext validate)
- {
- var extInstanceFeatures = _node.GetExtension<MeshExtInstanceFeatures>();
- validate.NotNull(nameof(extInstanceFeatures), extInstanceFeatures);
- var extMeshGpInstancing = _node.GetExtension<MeshGpuInstancing>();
- validate.NotNull(nameof(extMeshGpInstancing), extMeshGpInstancing);
- foreach (var instanceFeatureId in FeatureIds)
- {
- if (instanceFeatureId.Attribute.HasValue)
- {
- var expectedVertexAttribute = $"_FEATURE_ID_{instanceFeatureId.Attribute}";
- var gpuInstancing = _node.GetGpuInstancing();
- var featureIdAccessors = gpuInstancing.GetAccessor(expectedVertexAttribute);
- Guard.NotNull(featureIdAccessors, expectedVertexAttribute);
- }
- instanceFeatureId.ValidateFeatureIdReferences(_node.LogicalParent);
- }
- base.OnValidateReferences(validate);
- }
- protected override void OnValidateContent(ValidationContext validate)
- {
- var extInstanceFeatures = _node.GetExtension<MeshExtInstanceFeatures>();
- validate.NotNull(nameof(FeatureIds), extInstanceFeatures.FeatureIds);
- validate.IsTrue(nameof(FeatureIds), extInstanceFeatures.FeatureIds.Count > 0, "Instance FeatureIds has items");
- foreach (var instanceFeatureId in FeatureIds)
- {
- instanceFeatureId.ValidateFeatureIdContent();
- }
- base.OnValidateContent(validate);
- }
- #endregion
- }
- /// <remarks>
- /// This extension is attached to a <see cref="Schema2.MeshPrimitive"/>
- /// </remarks>
- public partial class MeshExtMeshFeatures
- {
- #region lifecycle
- internal MeshExtMeshFeatures(MeshPrimitive meshPrimitive)
- {
- _meshPrimitive = meshPrimitive;
- _featureIds = new ChildrenList<MeshExtMeshFeatureID, MeshExtMeshFeatures>(this);
- }
- protected override IEnumerable<ExtraProperties> GetLogicalChildren()
- {
- return base.GetLogicalChildren().Concat(_featureIds);
- }
- #endregion
- #region data
- private MeshPrimitive _meshPrimitive;
- #endregion
- #region properties
- public MeshPrimitive LogicalParent => _meshPrimitive;
- public IReadOnlyList<MeshExtMeshFeatureID> FeatureIds => _featureIds;
- #endregion
- #region API
- public MeshExtMeshFeatureID CreateFeatureID(IMeshFeatureIDInfo properties, Texture texture = null, IReadOnlyList<int> texChannels = null)
- {
- var instance = CreateFeatureID();
- instance.FeatureCount = properties.FeatureCount;
- instance.NullFeatureId = properties.NullFeatureId;
- instance.Label = properties.Label;
- instance.Attribute = properties.Attribute;
- instance.PropertyTable = properties.PropertyTable;
- if (texture != null)
- {
- var texInfo = instance.UseTexture();
- texInfo.Texture = texture;
- if (texChannels != null) texInfo.SetChannels(texChannels);
- }
- return instance;
- }
- public MeshExtMeshFeatureID CreateFeatureID()
- {
- var featureId = new MeshExtMeshFeatureID();
- _featureIds.Add(featureId);
- return featureId;
- }
- #endregion
- #region validation
- protected override void OnValidateReferences(ValidationContext validate)
- {
- foreach (var featureId in _featureIds)
- {
- if (featureId.Attribute.HasValue)
- {
- var expectedVertexAttribute = $"_FEATURE_ID_{featureId.Attribute}";
- Guard.NotNull(_meshPrimitive.GetVertexAccessor(expectedVertexAttribute), expectedVertexAttribute);
- }
- featureId.ValidateFeatureIdReferences(_meshPrimitive.LogicalParent.LogicalParent);
- var texture = featureId.GetTexture();
- if (texture != null)
- {
- var expectedTexCoordAttribute = $"TEXCOORD_{texture.TextureCoordinate}";
- Guard.NotNull(_meshPrimitive.GetVertexAccessor(expectedTexCoordAttribute), expectedTexCoordAttribute);
- var modelRoot = _meshPrimitive.LogicalParent.LogicalParent;
- validate.IsNullOrIndex(nameof(texture), texture.TextureCoordinate, modelRoot.LogicalTextures);
- }
- }
- base.OnValidateReferences(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();
- }
- base.OnValidateContent(validate);
- }
- #endregion
- }
- }
- }
|