parseFeatureMetadataLegacy.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import Check from "../Core/Check.js";
  2. import combine from "../Core/combine.js";
  3. import defaultValue from "../Core/defaultValue.js";
  4. import defined from "../Core/defined.js";
  5. import PropertyTable from "./PropertyTable.js";
  6. import PropertyTexture from "./PropertyTexture.js";
  7. import StructuralMetadata from "./StructuralMetadata.js";
  8. import MetadataTable from "./MetadataTable.js";
  9. /**
  10. * Parse the <code>EXT_feature_metadata</code> glTF extension to create a
  11. * structural metadata object.
  12. *
  13. * @param {object} options Object with the following properties:
  14. * @param {object} options.extension The extension JSON object.
  15. * @param {MetadataSchema} options.schema The parsed schema.
  16. * @param {Object<string, Uint8Array>} [options.bufferViews] An object mapping bufferView IDs to Uint8Array objects.
  17. * @param {Object<string, Texture>} [options.textures] An object mapping texture IDs to {@link Texture} objects.
  18. * @return {StructuralMetadata} A structural metadata object
  19. * @private
  20. * @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
  21. */
  22. function parseFeatureMetadataLegacy(options) {
  23. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  24. const extension = options.extension;
  25. // The calling code is responsible for loading the schema.
  26. // This keeps metadata parsing synchronous.
  27. const schema = options.schema;
  28. //>>includeStart('debug', pragmas.debug);
  29. Check.typeOf.object("options.extension", extension);
  30. Check.typeOf.object("options.schema", schema);
  31. //>>includeEnd('debug');
  32. let i;
  33. const propertyTables = [];
  34. let sortedIds;
  35. if (defined(extension.featureTables)) {
  36. // Store textures in an array sorted by the dictionary keys. This
  37. // allows compatibility with the newer EXT_structural_metadata extension
  38. // which is array-based.
  39. sortedIds = Object.keys(extension.featureTables).sort();
  40. for (i = 0; i < sortedIds.length; i++) {
  41. const featureTableId = sortedIds[i];
  42. const featureTable = extension.featureTables[featureTableId];
  43. const classDefinition = schema.classes[featureTable.class];
  44. const metadataTable = new MetadataTable({
  45. count: featureTable.count,
  46. properties: featureTable.properties,
  47. class: classDefinition,
  48. bufferViews: options.bufferViews,
  49. });
  50. propertyTables.push(
  51. new PropertyTable({
  52. id: featureTableId,
  53. count: featureTable.count,
  54. metadataTable: metadataTable,
  55. extras: featureTable.extras,
  56. extensions: featureTable.extensions,
  57. })
  58. );
  59. }
  60. }
  61. const propertyTextures = [];
  62. if (defined(extension.featureTextures)) {
  63. // Store textures in an array sorted by the dictionary keys. This
  64. // allows compatibility with the newer EXT_structural_metadata extension
  65. // which is array-based.
  66. sortedIds = Object.keys(extension.featureTextures).sort();
  67. for (i = 0; i < sortedIds.length; i++) {
  68. const featureTextureId = sortedIds[i];
  69. const featureTexture = extension.featureTextures[featureTextureId];
  70. propertyTextures.push(
  71. new PropertyTexture({
  72. id: featureTextureId,
  73. propertyTexture: transcodeToPropertyTexture(featureTexture),
  74. class: schema.classes[featureTexture.class],
  75. textures: options.textures,
  76. })
  77. );
  78. }
  79. }
  80. return new StructuralMetadata({
  81. schema: schema,
  82. propertyTables: propertyTables,
  83. propertyTextures: propertyTextures,
  84. statistics: extension.statistics,
  85. extras: extension.extras,
  86. extensions: extension.extensions,
  87. });
  88. }
  89. function transcodeToPropertyTexture(featureTexture) {
  90. const propertyTexture = {
  91. class: featureTexture.class,
  92. properties: {},
  93. };
  94. const properties = featureTexture.properties;
  95. for (const propertyId in properties) {
  96. if (properties.hasOwnProperty(propertyId)) {
  97. const oldProperty = properties[propertyId];
  98. const property = {
  99. // EXT_structural_metadata uses numeric channel indices instead of
  100. // a string of channel letters like "rgba".
  101. channels: reformatChannels(oldProperty.channels),
  102. extras: oldProperty.extras,
  103. extensions: oldProperty.extensions,
  104. };
  105. // EXT_feature_metadata puts the textureInfo in property.texture.
  106. // EXT_structural_metadata flattens this structure; essentially a
  107. // textureInfo + channels
  108. propertyTexture.properties[propertyId] = combine(
  109. oldProperty.texture,
  110. property,
  111. true
  112. );
  113. }
  114. }
  115. return propertyTexture;
  116. }
  117. function reformatChannels(channelsString) {
  118. const length = channelsString.length;
  119. const result = new Array(length);
  120. for (let i = 0; i < length; i++) {
  121. result[i] = "rgba".indexOf(channelsString[i]);
  122. }
  123. return result;
  124. }
  125. export default parseFeatureMetadataLegacy;