VoxelContent.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import Check from "../Core/Check.js";
  2. import DeveloperError from "../Core/DeveloperError.js";
  3. import defined from "../Core/defined.js";
  4. import getJsonFromTypedArray from "../Core/getJsonFromTypedArray.js";
  5. import MetadataTable from "./MetadataTable.js";
  6. /**
  7. * An object representing voxel content for a {@link Cesium3DTilesVoxelProvider}.
  8. *
  9. * @alias VoxelContent
  10. * @constructor
  11. *
  12. * @param {Resource} resource The resource for this voxel content. This is used for fetching external buffers as needed.
  13. *
  14. * @private
  15. * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
  16. */
  17. function VoxelContent(resource) {
  18. //>>includeStart('debug', pragmas.debug);
  19. Check.typeOf.object("resource", resource);
  20. //>>includeEnd('debug');
  21. this._resource = resource;
  22. this._metadataTable = undefined;
  23. }
  24. Object.defineProperties(VoxelContent.prototype, {
  25. /**
  26. * The {@link MetadataTable} storing voxel property values.
  27. *
  28. * @type {MetadataTable}
  29. * @readonly
  30. * @private
  31. */
  32. metadataTable: {
  33. get: function () {
  34. return this._metadataTable;
  35. },
  36. },
  37. });
  38. /**
  39. * Creates an object representing voxel content for a {@link Cesium3DTilesVoxelProvider}.
  40. *
  41. * @param {Resource} resource The resource for this voxel content. This is used for fetching external buffers as needed.
  42. * @param {object} [json] Voxel JSON contents. Mutually exclusive with binary.
  43. * @param {Uint8Array} [binary] Voxel binary contents. Mutually exclusive with json.
  44. * @param {MetadataSchema} metadataSchema The metadata schema used by property tables in the voxel content
  45. * @returns {Promise<VoxelContent>}
  46. *
  47. * @exception {DeveloperError} One of json and binary must be defined.
  48. */
  49. VoxelContent.fromJson = async function (
  50. resource,
  51. json,
  52. binary,
  53. metadataSchema
  54. ) {
  55. //>>includeStart('debug', pragmas.debug);
  56. Check.typeOf.object("resource", resource);
  57. if (defined(json) === defined(binary)) {
  58. throw new DeveloperError("One of json and binary must be defined.");
  59. }
  60. //>>includeEnd('debug');
  61. let chunks;
  62. if (defined(json)) {
  63. chunks = {
  64. json: json,
  65. binary: undefined,
  66. };
  67. } else {
  68. chunks = parseVoxelChunks(binary);
  69. }
  70. const buffersU8 = await requestBuffers(resource, chunks.json, chunks.binary);
  71. const bufferViewsU8 = {};
  72. const bufferViewsLength = chunks.json.bufferViews.length;
  73. for (let i = 0; i < bufferViewsLength; ++i) {
  74. const bufferViewJson = chunks.json.bufferViews[i];
  75. const start = bufferViewJson.byteOffset;
  76. const end = start + bufferViewJson.byteLength;
  77. const buffer = buffersU8[bufferViewJson.buffer];
  78. const bufferView = buffer.subarray(start, end);
  79. bufferViewsU8[i] = bufferView;
  80. }
  81. const propertyTableIndex = chunks.json.voxelTable;
  82. const propertyTableJson = chunks.json.propertyTables[propertyTableIndex];
  83. const content = new VoxelContent(resource);
  84. content._metadataTable = new MetadataTable({
  85. count: propertyTableJson.count,
  86. properties: propertyTableJson.properties,
  87. class: metadataSchema.classes[propertyTableJson.class],
  88. bufferViews: bufferViewsU8,
  89. });
  90. return content;
  91. };
  92. function requestBuffers(resource, json, binary) {
  93. const buffersLength = json.buffers.length;
  94. const bufferPromises = new Array(buffersLength);
  95. for (let i = 0; i < buffersLength; i++) {
  96. const buffer = json.buffers[i];
  97. if (defined(buffer.uri)) {
  98. const baseResource = resource;
  99. const bufferResource = baseResource.getDerivedResource({
  100. url: buffer.uri,
  101. });
  102. bufferPromises[i] = bufferResource
  103. .fetchArrayBuffer()
  104. .then(function (arrayBuffer) {
  105. return new Uint8Array(arrayBuffer);
  106. });
  107. } else {
  108. bufferPromises[i] = Promise.resolve(binary);
  109. }
  110. }
  111. return Promise.all(bufferPromises);
  112. }
  113. /**
  114. * A helper object for storing the two parts of the binary voxel content
  115. *
  116. * @typedef {object} VoxelChunks
  117. * @property {object} json The json chunk of the binary voxel content
  118. * @property {Uint8Array} binary The binary chunk of the binary voxel content. This represents the internal buffer.
  119. * @private
  120. */
  121. /**
  122. * Given binary voxel content, split into JSON and binary chunks
  123. *
  124. * @param {Uint8Array} binaryView The binary voxel content
  125. * @returns {VoxelChunks} An object containing the JSON and binary chunks
  126. * @private
  127. */
  128. function parseVoxelChunks(binaryView) {
  129. // Parse the header
  130. const littleEndian = true;
  131. const reader = new DataView(binaryView.buffer, binaryView.byteOffset);
  132. // Skip to the chunk lengths
  133. let byteOffset = 8;
  134. // Read the bottom 32 bits of the 64-bit byte length. This is ok for now because:
  135. // 1) not all browsers have native 64-bit operations
  136. // 2) the data is well under 4GB
  137. const jsonByteLength = reader.getUint32(byteOffset, littleEndian);
  138. byteOffset += 8;
  139. const binaryByteLength = reader.getUint32(byteOffset, littleEndian);
  140. byteOffset += 8;
  141. const json = getJsonFromTypedArray(binaryView, byteOffset, jsonByteLength);
  142. byteOffset += jsonByteLength;
  143. const binary = binaryView.subarray(byteOffset, byteOffset + binaryByteLength);
  144. return {
  145. json: json,
  146. binary: binary,
  147. };
  148. }
  149. export default VoxelContent;