parseBatchTable.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. import Check from "../Core/Check.js";
  2. import defined from "../Core/defined.js";
  3. import deprecationWarning from "../Core/deprecationWarning.js";
  4. import RuntimeError from "../Core/RuntimeError.js";
  5. import BatchTableHierarchy from "./BatchTableHierarchy.js";
  6. import StructuralMetadata from "./StructuralMetadata.js";
  7. import PropertyTable from "./PropertyTable.js";
  8. import getBinaryAccessor from "./getBinaryAccessor.js";
  9. import JsonMetadataTable from "./JsonMetadataTable.js";
  10. import MetadataClass from "./MetadataClass.js";
  11. import MetadataSchema from "./MetadataSchema.js";
  12. import MetadataTable from "./MetadataTable.js";
  13. /**
  14. * An object that parses the the 3D Tiles 1.0 batch table and transcodes it to
  15. * be compatible with structural metadata from the <code>EXT_structural_metadata</code> glTF extension
  16. * <p>
  17. * See the {@link https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata|EXT_structural_metadata Extension} for glTF.
  18. * </p>
  19. *
  20. * @param {Object} options Object with the following properties:
  21. * @param {Number} options.count The number of features in the batch table.
  22. * @param {Object} options.batchTable The batch table JSON
  23. * @param {Uint8Array} [options.binaryBody] The batch table binary body
  24. * @return {StructuralMetadata} A transcoded structural metadata object
  25. *
  26. * @private
  27. * @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.
  28. */
  29. export default function parseBatchTable(options) {
  30. //>>includeStart('debug', pragmas.debug);
  31. Check.typeOf.number("options.count", options.count);
  32. Check.typeOf.object("options.batchTable", options.batchTable);
  33. //>>includeEnd('debug');
  34. const featureCount = options.count;
  35. const batchTable = options.batchTable;
  36. const binaryBody = options.binaryBody;
  37. // divide properties into binary, json and hierarchy
  38. const partitionResults = partitionProperties(batchTable);
  39. const jsonMetadataTable = new JsonMetadataTable({
  40. count: featureCount,
  41. properties: partitionResults.jsonProperties,
  42. });
  43. const hierarchy = initializeHierarchy(partitionResults.hierarchy, binaryBody);
  44. const className = MetadataClass.BATCH_TABLE_CLASS_NAME;
  45. const binaryResults = transcodeBinaryProperties(
  46. featureCount,
  47. className,
  48. partitionResults.binaryProperties,
  49. binaryBody
  50. );
  51. const featureTableJson = binaryResults.featureTableJson;
  52. const metadataTable = new MetadataTable({
  53. count: featureTableJson.count,
  54. properties: featureTableJson.properties,
  55. class: binaryResults.transcodedClass,
  56. bufferViews: binaryResults.bufferViewsU8,
  57. });
  58. const propertyTable = new PropertyTable({
  59. id: 0,
  60. name: "Batch Table",
  61. count: featureTableJson.count,
  62. metadataTable: metadataTable,
  63. jsonMetadataTable: jsonMetadataTable,
  64. batchTableHierarchy: hierarchy,
  65. });
  66. return new StructuralMetadata({
  67. schema: binaryResults.transcodedSchema,
  68. propertyTables: [propertyTable],
  69. extensions: partitionResults.extensions,
  70. extras: partitionResults.extras,
  71. });
  72. }
  73. /**
  74. * Divide the batch table's properties into binary, JSON and hierarchy
  75. * extension as each is handled separately
  76. *
  77. * @param {Object} batchTable The batch table JSON
  78. * @returns {Object} The batch table divided into binary, JSON and hierarchy portions. Extras and extensions are also divided out for ease of processing.
  79. *
  80. * @private
  81. */
  82. function partitionProperties(batchTable) {
  83. const legacyHierarchy = batchTable.HIERARCHY;
  84. const extras = batchTable.extras;
  85. const extensions = batchTable.extensions;
  86. let hierarchyExtension;
  87. if (defined(legacyHierarchy)) {
  88. parseBatchTable._deprecationWarning(
  89. "batchTableHierarchyExtension",
  90. "The batch table HIERARCHY property has been moved to an extension. Use extensions.3DTILES_batch_table_hierarchy instead."
  91. );
  92. hierarchyExtension = legacyHierarchy;
  93. } else if (defined(extensions)) {
  94. hierarchyExtension = extensions["3DTILES_batch_table_hierarchy"];
  95. }
  96. const jsonProperties = {};
  97. const binaryProperties = {};
  98. for (const propertyId in batchTable) {
  99. if (
  100. !batchTable.hasOwnProperty(propertyId) ||
  101. // these cases were handled above;
  102. propertyId === "HIERARCHY" ||
  103. propertyId === "extensions" ||
  104. propertyId === "extras"
  105. ) {
  106. continue;
  107. }
  108. const property = batchTable[propertyId];
  109. if (Array.isArray(property)) {
  110. jsonProperties[propertyId] = property;
  111. } else {
  112. binaryProperties[propertyId] = property;
  113. }
  114. }
  115. return {
  116. binaryProperties: binaryProperties,
  117. jsonProperties: jsonProperties,
  118. hierarchy: hierarchyExtension,
  119. extras: extras,
  120. extensions: extensions,
  121. };
  122. }
  123. /**
  124. * Transcode the binary properties of the batch table to be compatible with
  125. * <code>EXT_structural_metadata</code>
  126. *
  127. * @param {Number} featureCount The number of features in the batch table
  128. * @param {String} className The name of the metadata class to be created.
  129. * @param {Object.<String, Object>} binaryProperties A dictionary of property ID to property definition
  130. * @param {Uint8Array} [binaryBody] The binary body of the batch table
  131. * @return {Object} Transcoded data needed for constructing a {@link StructuralMetadata} object.
  132. *
  133. * @private
  134. */
  135. function transcodeBinaryProperties(
  136. featureCount,
  137. className,
  138. binaryProperties,
  139. binaryBody
  140. ) {
  141. const classProperties = {};
  142. const featureTableProperties = {};
  143. const bufferViewsU8 = {};
  144. let bufferViewCount = 0;
  145. for (const propertyId in binaryProperties) {
  146. if (!binaryProperties.hasOwnProperty(propertyId)) {
  147. continue;
  148. }
  149. if (!defined(binaryBody)) {
  150. throw new RuntimeError(
  151. `Property ${propertyId} requires a batch table binary.`
  152. );
  153. }
  154. const property = binaryProperties[propertyId];
  155. const binaryAccessor = getBinaryAccessor(property);
  156. featureTableProperties[propertyId] = {
  157. bufferView: bufferViewCount,
  158. };
  159. classProperties[propertyId] = transcodePropertyType(property);
  160. bufferViewsU8[bufferViewCount] = binaryAccessor.createArrayBufferView(
  161. binaryBody.buffer,
  162. binaryBody.byteOffset + property.byteOffset,
  163. featureCount
  164. );
  165. bufferViewCount++;
  166. }
  167. const schemaJson = {
  168. classes: {},
  169. };
  170. schemaJson.classes[className] = {
  171. properties: classProperties,
  172. };
  173. const transcodedSchema = new MetadataSchema(schemaJson);
  174. const featureTableJson = {
  175. class: className,
  176. count: featureCount,
  177. properties: featureTableProperties,
  178. };
  179. return {
  180. featureTableJson: featureTableJson,
  181. bufferViewsU8: bufferViewsU8,
  182. transcodedSchema: transcodedSchema,
  183. transcodedClass: transcodedSchema.classes[className],
  184. };
  185. }
  186. /**
  187. * Given a property definition from the batch table, compute the equivalent
  188. * <code>EXT_structural_metadata</code> type definition
  189. *
  190. * @param {Object} property The batch table property definition
  191. * @return {Object} The corresponding structural metadata property definition
  192. * @private
  193. */
  194. function transcodePropertyType(property) {
  195. const componentType = transcodeComponentType(property.componentType);
  196. return {
  197. type: property.type,
  198. componentType: componentType,
  199. };
  200. }
  201. /**
  202. * Convert the component type of a batch table property to the corresponding
  203. * type used with structural metadata
  204. *
  205. * @property {String} componentType the batch table's component type
  206. * @return {String} The corresponding structural metadata data type
  207. *
  208. * @private
  209. */
  210. function transcodeComponentType(componentType) {
  211. switch (componentType) {
  212. case "BYTE":
  213. return "INT8";
  214. case "UNSIGNED_BYTE":
  215. return "UINT8";
  216. case "SHORT":
  217. return "INT16";
  218. case "UNSIGNED_SHORT":
  219. return "UINT16";
  220. case "INT":
  221. return "INT32";
  222. case "UNSIGNED_INT":
  223. return "UINT32";
  224. case "FLOAT":
  225. return "FLOAT32";
  226. case "DOUBLE":
  227. return "FLOAT64";
  228. }
  229. }
  230. /**
  231. * Construct a batch table hierarchy object if the <code>3DTILES_batch_table_hierarchy</code> extension is present
  232. *
  233. * @param {Object} [hierarchyExtension] The <code>3DTILES_batch_table_hierarchy</code> extension object.
  234. * @param {Uint8Array} binaryBody The binary body of the batch table
  235. * @return {BatchTableHierarchy} A batch table hierarchy, or <code>undefined</code> if the extension is not present.
  236. *
  237. * @private
  238. */
  239. function initializeHierarchy(hierarchyExtension, binaryBody) {
  240. if (defined(hierarchyExtension)) {
  241. return new BatchTableHierarchy({
  242. extension: hierarchyExtension,
  243. binaryBody: binaryBody,
  244. });
  245. }
  246. return undefined;
  247. }
  248. // exposed for testing
  249. parseBatchTable._deprecationWarning = deprecationWarning;