Skip to content

Commit de297f0

Browse files
committed
progress on cesium API redesign++
1 parent 22b73f6 commit de297f0

File tree

11 files changed

+1028
-678
lines changed

11 files changed

+1028
-678
lines changed

build/SharpGLTF.CodeGen/Ext.EXT_Structural_Metadata.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ public override void PrepareTypes(CSharpEmitter newEmitter, SchemaType.Context c
2323
newEmitter.SetRuntimeName("Property Texture in EXT_structural_metadata", "PropertyTexture", Constants.CesiumNameSpace);
2424
newEmitter.SetRuntimeName("Property Texture Property in EXT_structural_metadata", "PropertyTextureProperty", Constants.CesiumNameSpace);
2525
newEmitter.SetRuntimeName("Property Attribute Property in EXT_structural_metadata", "PropertyAttributeProperty", Constants.CesiumNameSpace);
26-
newEmitter.SetRuntimeName("Class Property in EXT_structural_metadata", "ClassProperty", Constants.CesiumNameSpace);
26+
newEmitter.SetRuntimeName("Class Property in EXT_structural_metadata", "StructuralMetadataClassProperty", Constants.CesiumNameSpace);
2727
newEmitter.SetRuntimeName("Class in EXT_structural_metadata", "StructuralMetadataClass", Constants.CesiumNameSpace);
28-
newEmitter.SetRuntimeName("Enum Value in EXT_structural_metadata", "EnumValue", Constants.CesiumNameSpace);
28+
newEmitter.SetRuntimeName("Enum Value in EXT_structural_metadata", "StructuralMetadataEnumValue", Constants.CesiumNameSpace);
2929
newEmitter.SetRuntimeName("Enum in EXT_structural_metadata", "StructuralMetadataEnum", Constants.CesiumNameSpace);
3030
newEmitter.SetRuntimeName("Property Attribute in EXT_structural_metadata", "PropertyAttribute", Constants.CesiumNameSpace);
3131

@@ -38,15 +38,15 @@ public override void PrepareTypes(CSharpEmitter newEmitter, SchemaType.Context c
3838
newEmitter.SetFieldToChildrenList(ctx, "EXT_structural_metadata glTF extension", "propertyAttributes");
3939
newEmitter.SetFieldToChildrenList(ctx, "EXT_structural_metadata glTF extension", "propertyTextures");
4040

41+
newEmitter.SetFieldToChildrenDictionary(ctx, "Property Attribute in EXT_structural_metadata", "properties");
4142
newEmitter.SetFieldToChildrenDictionary(ctx, "Property Texture in EXT_structural_metadata", "properties");
42-
43-
newEmitter.SetFieldToChildrenDictionary(ctx, "Class in EXT_structural_metadata", "properties");
44-
4543
newEmitter.SetFieldToChildrenDictionary(ctx, "Property Table in EXT_structural_metadata", "properties");
4644

47-
newEmitter.SetFieldToChildrenDictionary(ctx, "Property Attribute in EXT_structural_metadata", "properties");
4845

46+
newEmitter.SetFieldToChildrenDictionary(ctx, "Class in EXT_structural_metadata", "properties");
4947
newEmitter.SetFieldToChildrenDictionary(ctx, "Schema in EXT_structural_metadata", "classes");
48+
49+
newEmitter.SetFieldToChildrenList(ctx, "Enum in EXT_structural_metadata", "values");
5050
newEmitter.SetFieldToChildrenDictionary(ctx, "Schema in EXT_structural_metadata", "enums");
5151
}
5252

src/SharpGLTF.Ext.3DTiles/Memory/BinaryTable.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ private static byte[] Vector4ToBytes<T>(IReadOnlyList<T> values)
151151
return result;
152152
}
153153

154-
public static List<int> GetStringOffsets(List<string> values)
154+
public static List<int> GetStringOffsets(IReadOnlyList<string> values)
155155
{
156156
var offsets = new List<int>() { 0 };
157157
foreach (var value in values)

src/SharpGLTF.Ext.3DTiles/Schema2/Ext.FeatureID.cs

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ namespace SharpGLTF.Schema2.Tiles3D
77
{
88
using Collections;
99

10+
/// <summary>
11+
/// Mesh Feature Ids
12+
/// </summary>
13+
/// <remarks>
14+
/// Implemented by <see cref="MeshExtInstanceFeatureID"/> and <see cref="MeshExtMeshFeatureID"/>
15+
/// </remarks>
1016
public interface IMeshFeatureIDInfo
1117
{
1218
/// <summary>
@@ -34,7 +40,54 @@ public interface IMeshFeatureIDInfo
3440
/// <summary>
3541
/// The index of the property table containing per-feature property values. Only applicable when using the `EXT_structural_metadata` extension.
3642
/// </summary>
37-
public int? PropertyTable { get; set; }
43+
public int? PropertyTableIndex { get; set; }
44+
}
45+
46+
public sealed class FeatureIDBuilder : IMeshFeatureIDInfo , IEquatable<IMeshFeatureIDInfo>
47+
{
48+
public FeatureIDBuilder(int featureCount, string label = null)
49+
{
50+
FeatureCount = featureCount;
51+
Label = label;
52+
}
53+
54+
public FeatureIDBuilder(int featureCount, int attribute, string label = null)
55+
{
56+
FeatureCount = featureCount;
57+
Attribute = attribute;
58+
59+
Label = label;
60+
}
61+
62+
public FeatureIDBuilder(PropertyTable table, int? attribute = null, string label = null)
63+
{
64+
FeatureCount = table.Count;
65+
Attribute = attribute;
66+
_root = table.LogicalParent;
67+
PropertyTableIndex = table.LogicalIndex;
68+
69+
Label = label;
70+
}
71+
72+
private readonly EXTStructuralMetadataRoot _root;
73+
74+
public int FeatureCount { get; set; }
75+
public int? NullFeatureId { get; set; }
76+
public int? Attribute { get; set; }
77+
public string Label { get; set; }
78+
public int? PropertyTableIndex { get; set; }
79+
80+
public bool Equals(IMeshFeatureIDInfo other)
81+
{
82+
if (other == null) return false;
83+
if (this.FeatureCount != other.FeatureCount) return false;
84+
if (this.NullFeatureId != other.NullFeatureId) return false;
85+
if (this.Attribute != other.Attribute) return false;
86+
if (this.Label != other.Label) return false;
87+
if (this.PropertyTableIndex != other.PropertyTableIndex) return false;
88+
89+
return true;
90+
}
3891
}
3992

4093
/// <remarks>
@@ -44,14 +97,15 @@ public partial class MeshExtInstanceFeatureID : IChildOfList<MeshExtInstanceFeat
4497
{
4598
#region lifecycle
4699

100+
/*
47101
public MeshExtInstanceFeatureID(int featureCount, int? attribute = null, int? propertyTable = null, string label = null, int? nullFeatureId = null)
48102
{
49103
FeatureCount = featureCount;
50104
Attribute = attribute;
51105
Label = label;
52-
PropertyTable = propertyTable;
106+
PropertyTableIndex = propertyTable;
53107
NullFeatureId = nullFeatureId;
54-
}
108+
}*/
55109

56110

57111
internal MeshExtInstanceFeatureID() { }
@@ -78,7 +132,7 @@ void IChildOfList<MeshExtInstanceFeatures>.SetLogicalParent(MeshExtInstanceFeatu
78132

79133
#endregion
80134

81-
#region properties
135+
#region IMeshFeatureIDInfo properties
82136
public int FeatureCount
83137
{
84138
get => _featureCount;
@@ -111,7 +165,7 @@ public string Label
111165
_label = value;
112166
}
113167
}
114-
public int? PropertyTable
168+
public int? PropertyTableIndex
115169
{
116170
get => _propertyTable;
117171
set
@@ -158,7 +212,7 @@ void IChildOfList<MeshExtMeshFeatures>.SetLogicalParent(MeshExtMeshFeatures pare
158212

159213
#endregion
160214

161-
#region properties
215+
#region IMeshFeatureIDInfo properties
162216
public int FeatureCount
163217
{
164218
get => _featureCount;
@@ -191,7 +245,7 @@ public string Label
191245
_label = value;
192246
}
193247
}
194-
public int? PropertyTable
248+
public int? PropertyTableIndex
195249
{
196250
get => _propertyTable;
197251
set
@@ -205,6 +259,9 @@ public int? PropertyTable
205259

206260
#region API
207261

262+
// question: is _texture required to always exist? if that would be the case, then it should be created
263+
// in the constructor an exposed as a read only property.
264+
208265
/// <summary>
209266
/// Gets a texture containing feature IDs.
210267
/// </summary>
@@ -276,6 +333,7 @@ private ModelRoot _GetModelRoot()
276333
public void SetChannels(IReadOnlyList<int> channels)
277334
{
278335
Guard.NotNullOrEmpty(channels, nameof(channels));
336+
Guard.MustBeGreaterThanOrEqualTo(channels.Count, _channelsMinItems, nameof(channels));
279337

280338
_channels.Clear();
281339
_channels.AddRange(channels);

src/SharpGLTF.Ext.3DTiles/Schema2/Ext.Features.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ partial class Tiles3DExtensions
1414
{
1515
internal static void ValidateFeatureIdReferences(this IMeshFeatureIDInfo featureId, ModelRoot root)
1616
{
17-
if (featureId.PropertyTable.HasValue)
17+
if (featureId.PropertyTableIndex.HasValue)
1818
{
1919
var metadataExtension = root.GetExtension<EXTStructuralMetadataRoot>();
2020
Guard.NotNull(metadataExtension, nameof(metadataExtension), "EXT_Structural_Metadata extension is not found.");
21-
Guard.NotNull(metadataExtension.PropertyTables[featureId.PropertyTable.Value], nameof(featureId.PropertyTable), $"Property table index {featureId.PropertyTable.Value} does not exist");
21+
Guard.NotNull(metadataExtension.PropertyTables[featureId.PropertyTableIndex.Value], nameof(featureId.PropertyTableIndex), $"Property table index {featureId.PropertyTableIndex.Value} does not exist");
2222
}
2323
}
2424

@@ -40,9 +40,9 @@ internal static void ValidateFeatureIdContent(this IMeshFeatureIDInfo featureId)
4040
{
4141
Guard.MustBeGreaterThanOrEqualTo((int)featureId.Attribute, 0, nameof(featureId.Attribute));
4242
}
43-
if (featureId.PropertyTable.HasValue)
43+
if (featureId.PropertyTableIndex.HasValue)
4444
{
45-
Guard.MustBeGreaterThanOrEqualTo((int)featureId.PropertyTable, 0, nameof(featureId.PropertyTable));
45+
Guard.MustBeGreaterThanOrEqualTo((int)featureId.PropertyTableIndex, 0, nameof(featureId.PropertyTableIndex));
4646
}
4747
}
4848

@@ -134,7 +134,7 @@ public MeshExtInstanceFeatureID CreateFeatureID(IMeshFeatureIDInfo properties)
134134
instance.NullFeatureId = properties.NullFeatureId;
135135
instance.Label = properties.Label;
136136
instance.Attribute = properties.Attribute;
137-
instance.PropertyTable = properties.PropertyTable;
137+
instance.PropertyTableIndex = properties.PropertyTableIndex;
138138

139139
return instance;
140140
}
@@ -234,7 +234,7 @@ public MeshExtMeshFeatureID CreateFeatureID(IMeshFeatureIDInfo properties, Textu
234234
instance.NullFeatureId = properties.NullFeatureId;
235235
instance.Label = properties.Label;
236236
instance.Attribute = properties.Attribute;
237-
instance.PropertyTable = properties.PropertyTable;
237+
instance.PropertyTableIndex = properties.PropertyTableIndex;
238238

239239
if (texture != null)
240240
{
Lines changed: 82 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Linq;
3+
using System.Collections.Generic;
24

35
using SharpGLTF.Validation;
46

@@ -8,69 +10,125 @@ namespace SharpGLTF.Schema2
810

911
partial class Tiles3DExtensions
1012
{
11-
public static void SetPropertyTextures(this MeshPrimitive primitive, List<int> propertyTextures)
12-
{
13-
if (propertyTextures == null) { primitive.RemoveExtensions<ExtStructuralMetadataMeshPrimitive>(); return; }
13+
// TODO: PropertyTexture is taken from a Schema, but it is possible the schema is an external file,
14+
// in which case we could not have a PopertyTexture, just a blind ID
15+
16+
// Solution1: enforce loading the schema as part of the memory document
17+
// Solution2: allow the API to be OneOf<int,PropertyTexture>
1418

19+
public static void AddPropertyTexture(this MeshPrimitive primitive, PropertyTexture texture)
20+
{
1521
var ext = primitive.UseExtension<ExtStructuralMetadataMeshPrimitive>();
16-
ext.PropertyTextures = propertyTextures;
22+
ext.AddTexture(texture);
1723
}
1824

19-
public static void SetPropertyAttributes(this MeshPrimitive primitive, List<int> propertyAttributes)
25+
public static void AddPropertyAttribute(this MeshPrimitive primitive, PropertyAttribute attribute)
2026
{
21-
if (propertyAttributes == null) { primitive.RemoveExtensions<ExtStructuralMetadataMeshPrimitive>(); return; }
22-
2327
var ext = primitive.UseExtension<ExtStructuralMetadataMeshPrimitive>();
24-
ext.PropertyAttributes = propertyAttributes;
28+
ext.AddAttribute(attribute);
2529
}
2630
}
2731

2832
namespace Tiles3D
2933
{
3034
partial class ExtStructuralMetadataMeshPrimitive
3135
{
36+
#region lifecycle
3237
internal ExtStructuralMetadataMeshPrimitive(MeshPrimitive meshPrimitive)
3338
{
3439
this.meshPrimitive = meshPrimitive;
3540
_propertyTextures = new List<int>();
3641
_propertyAttributes = new List<int>();
3742
}
3843

44+
#endregion
45+
46+
#region data
47+
3948
private MeshPrimitive meshPrimitive;
4049

41-
public List<int> PropertyTextures
50+
#endregion
51+
52+
#region properties
53+
54+
private ModelRoot _GetModelRoot() => meshPrimitive.LogicalParent.LogicalParent;
55+
56+
public int PropertyCount => _propertyTextures.Count;
57+
58+
public int AttributeCount => _propertyAttributes.Count;
59+
60+
#endregion
61+
62+
#region API
63+
64+
public PropertyTexture GetTexture(int index)
4265
{
43-
get => _propertyTextures;
44-
set => _propertyTextures = value;
66+
Guard.MustBeBetweenOrEqualTo(index, 0, _propertyTextures.Count - 1, nameof(index));
67+
68+
var root = _GetModelRoot();
69+
var metadata = root.GetExtension<EXTStructuralMetadataRoot>();
70+
Guard.NotNull(metadata, nameof(index));
71+
72+
return metadata.PropertyTextures[index];
4573
}
4674

47-
public List<int> PropertyAttributes
75+
public void AddTexture(PropertyTexture texture)
4876
{
49-
get => _propertyAttributes;
50-
set => _propertyAttributes = value;
77+
Guard.NotNull(texture, nameof(texture));
78+
79+
var metadata = _GetModelRoot().UseExtension<EXTStructuralMetadataRoot>();
80+
var properties = metadata.PropertyTextures;
81+
Guard.IsTrue(properties.Contains(texture), nameof(texture));
82+
83+
_propertyTextures.Add(texture.LogicalIndex);
5184
}
5285

86+
public PropertyAttribute GetAttribute(int index)
87+
{
88+
Guard.MustBeBetweenOrEqualTo(index, 0, _propertyTextures.Count - 1, nameof(index));
89+
90+
var root = _GetModelRoot();
91+
var metadata = root.GetExtension<EXTStructuralMetadataRoot>();
92+
Guard.NotNull(metadata, nameof(index));
93+
94+
return metadata.PropertyAttributes[index];
95+
}
96+
97+
public void AddAttribute(PropertyAttribute attribute)
98+
{
99+
Guard.NotNull(attribute, nameof(attribute));
100+
101+
var metadata = _GetModelRoot().UseExtension<EXTStructuralMetadataRoot>();
102+
var properties = metadata.PropertyAttributes;
103+
Guard.IsTrue(properties.Contains(attribute), nameof(attribute));
104+
105+
_propertyAttributes.Add(attribute.LogicalIndex);
106+
}
107+
108+
#endregion
109+
110+
#region validation
111+
53112
protected override void OnValidateReferences(ValidationContext validate)
54113
{
55-
foreach (var propertyTexture in PropertyTextures)
114+
var rootMetadata = _GetModelRoot().GetExtension<EXTStructuralMetadataRoot>();
115+
116+
foreach (var propertyTexture in _propertyTextures)
56117
{
57-
var propertyTextures = meshPrimitive.LogicalParent.LogicalParent.GetExtension<EXTStructuralMetadataRoot>().PropertyTextures;
118+
var propertyTextures = rootMetadata.PropertyTextures;
58119
validate.IsNullOrIndex(nameof(propertyTexture), propertyTexture, propertyTextures);
59120
}
60121

61-
foreach (var propertyAttribute in PropertyAttributes)
122+
foreach (var propertyAttribute in _propertyAttributes)
62123
{
63-
var propertyAttributes = meshPrimitive.LogicalParent.LogicalParent.GetExtension<EXTStructuralMetadataRoot>().PropertyAttributes;
124+
var propertyAttributes = rootMetadata.PropertyAttributes;
64125
validate.IsNullOrIndex(nameof(propertyAttribute), propertyAttribute, propertyAttributes);
65126
}
66127

67128
base.OnValidateReferences(validate);
68-
}
129+
}
69130

70-
protected override void OnValidateContent(ValidationContext result)
71-
{
72-
base.OnValidateContent(result);
73-
}
131+
#endregion
74132
}
75133
}
76134
}

0 commit comments

Comments
 (0)