智慧水务管理系统 - 精河县供水工程综合管理平台

VoxelContent.js 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import { destroyObject } from "@cesium/engine";
  2. import Check from "../Core/Check.js";
  3. import ComponentDatatype from "../Core/ComponentDatatype.js";
  4. import DeveloperError from "../Core/DeveloperError.js";
  5. import defined from "../Core/defined.js";
  6. import GltfLoader from "./GltfLoader.js";
  7. import MetadataComponentType from "./MetadataComponentType.js";
  8. import MetadataType from "./MetadataType.js";
  9. /**
  10. * <div class="notice">
  11. * To construct a VoxelContent, call {@link VoxelContent.fromMetadataArray} or {@link VoxelContent.fromGltf}. Do not call the constructor directly.
  12. * </div>
  13. * An object representing voxel content for a {@link Cesium3DTilesVoxelProvider}.
  14. *
  15. * @alias VoxelContent
  16. * @internalConstructor
  17. *
  18. * @privateParam {object} options An object with the following properties:
  19. * @privateParam {ResourceLoader} [options.loader] The loader used to load the voxel content.
  20. * @privateParam {Int8Array[]|Uint8Array[]|Int16Array[]|Uint16Array[]|Int32Array[]|Uint32Array[]|Float32Array[]|Float64Array[]} [options.metadata] The metadata for this voxel content.
  21. *
  22. * @exception {DeveloperError} One of loader and metadata must be defined.
  23. * @exception {DeveloperError} metadata must be an array of TypedArrays.
  24. *
  25. * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
  26. */
  27. function VoxelContent(options) {
  28. //>>includeStart('debug', pragmas.debug);
  29. Check.typeOf.object("options", options);
  30. if (!defined(options.loader)) {
  31. if (!defined(options.metadata)) {
  32. throw new DeveloperError("One of loader and metadata must be defined.");
  33. }
  34. if (!Array.isArray(options.metadata)) {
  35. throw new DeveloperError("metadata must be an array of TypedArrays.");
  36. }
  37. }
  38. //>>includeEnd('debug');
  39. const { loader, metadata } = options;
  40. this._loader = loader;
  41. this._metadata = metadata;
  42. this._resourcesLoaded = false;
  43. this._ready = false;
  44. }
  45. Object.defineProperties(VoxelContent.prototype, {
  46. /**
  47. * Returns true when the content is ready to render; otherwise false
  48. *
  49. * @memberof VoxelContent.prototype
  50. *
  51. * @type {boolean}
  52. * @readonly
  53. * @private
  54. */
  55. ready: {
  56. get: function () {
  57. return this._ready;
  58. },
  59. },
  60. /**
  61. * The metadata for this voxel content.
  62. * The metadata is an array of typed arrays, one for each field.
  63. * The data for one field is a flattened 3D array ordered by X, then Y, then Z.
  64. *
  65. * @memberof VoxelContent.prototype
  66. * @type {Int8Array[]|Uint8Array[]|Int16Array[]|Uint16Array[]|Int32Array[]|Uint32Array[]|Float32Array[]|Float64Array[]}
  67. * @readonly
  68. */
  69. metadata: {
  70. get: function () {
  71. return this._metadata;
  72. },
  73. },
  74. });
  75. /**
  76. * Constructs a VoxelContent from an array of metadata.
  77. *
  78. * @param {Int8Array[]|Uint8Array[]|Int16Array[]|Uint16Array[]|Int32Array[]|Uint32Array[]|Float32Array[]|Float64Array[]} metadata The metadata to use for this voxel content.
  79. * @returns {VoxelContent} A VoxelContent containing the specified metadata.
  80. */
  81. VoxelContent.fromMetadataArray = function (metadata) {
  82. //>>includeStart('debug', pragmas.debug);
  83. Check.typeOf.object("metadata", metadata);
  84. if (!Array.isArray(metadata)) {
  85. throw new DeveloperError("metadata must be an array of TypedArrays.");
  86. }
  87. //>>includeEnd('debug');
  88. return new VoxelContent({ metadata });
  89. };
  90. /**
  91. * Constructs a VoxelContent from a glTF resource.
  92. *
  93. * @param {Resource} resource A Resource pointing to a glTF containing voxel content.
  94. * @returns {Promise<VoxelContent>} A promise that resolves to the voxel content.
  95. *
  96. * @private
  97. */
  98. VoxelContent.fromGltf = async function (resource) {
  99. //>>includeStart('debug', pragmas.debug);
  100. Check.typeOf.object("resource", resource);
  101. //>>includeEnd('debug');
  102. // Construct the glTF loader
  103. const loader = new GltfLoader({
  104. gltfResource: resource,
  105. releaseGltfJson: false,
  106. loadAttributesAsTypedArray: true,
  107. });
  108. try {
  109. // This loads the gltf JSON and ensures the gltf is valid
  110. // Further resource loading is handled synchronously in loader.process()
  111. // via voxelContent.update() as the frameState is needed
  112. await loader.load();
  113. } catch (error) {
  114. loader.destroy();
  115. throw error;
  116. }
  117. return new VoxelContent({ loader });
  118. };
  119. /**
  120. * Updates the content until all resources are ready for rendering.
  121. * @param {FrameState} frameState The frame state
  122. * @private
  123. */
  124. VoxelContent.prototype.update = function (primitive, frameState) {
  125. const loader = this._loader;
  126. if (this._ready) {
  127. // Nothing to do
  128. return;
  129. }
  130. // Ensures frames continue to render in requestRender mode while resources are processing
  131. frameState.afterRender.push(() => true);
  132. if (!defined(loader)) {
  133. this._ready = true;
  134. return;
  135. }
  136. if (this._resourcesLoaded) {
  137. const { structuralMetadata, scene } = loader.components;
  138. const { attributes } = scene.nodes[0].primitives[0];
  139. this._metadata = processAttributes(
  140. attributes,
  141. structuralMetadata,
  142. primitive,
  143. );
  144. this._ready = true;
  145. return;
  146. }
  147. this._resourcesLoaded = loader.process(frameState);
  148. };
  149. /**
  150. * Processes the attributes from the glTF loader, reordering them into the order expected by the primitive.
  151. *
  152. * @param {ModelComponents.Attribute[]} attributes The attributes to process
  153. * @param {StructuralMetadata} structuralMetadata Information from the glTF EXT_structural_metadata extension
  154. * @param {VoxelPrimitive} primitive The primitive for which this voxel content will be used.
  155. * @returns {Int8Array[]|Uint8Array[]|Int16Array[]|Uint16Array[]|Int32Array[]|Uint32Array[]|Float32Array[]|Float64Array[]} An array of typed arrays containing the attribute values
  156. * @private
  157. */
  158. function processAttributes(attributes, structuralMetadata, primitive) {
  159. const { className, names, types, componentTypes } = primitive.provider;
  160. const propertyAttribute = structuralMetadata.propertyAttributes.find(
  161. (p) => p.class.id === className,
  162. );
  163. const { properties } = propertyAttribute;
  164. const data = new Array(names.length);
  165. for (let i = 0; i < attributes.length; i++) {
  166. // Find the appropriate glTF attribute based on its name.
  167. const name = properties[names[i]].attribute;
  168. const attribute = attributes.find((a) => a.name === name);
  169. if (!defined(attribute)) {
  170. continue;
  171. }
  172. const componentDatatype = MetadataComponentType.toComponentDatatype(
  173. componentTypes[i],
  174. );
  175. const componentCount = MetadataType.getComponentCount(types[i]);
  176. const totalCount = attribute.count * componentCount;
  177. data[i] = ComponentDatatype.createArrayBufferView(
  178. componentDatatype,
  179. attribute.typedArray.buffer,
  180. attribute.typedArray.byteOffset + attribute.byteOffset,
  181. totalCount,
  182. );
  183. }
  184. return data;
  185. }
  186. /**
  187. * Returns true if this object was destroyed; otherwise, false.
  188. * <br /><br />
  189. * If this object was destroyed, it should not be used; calling any function other than
  190. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  191. *
  192. * @returns {boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  193. *
  194. * @see VoxelContent#destroy
  195. *
  196. * @private
  197. */
  198. VoxelContent.prototype.isDestroyed = function () {
  199. return false;
  200. };
  201. /**
  202. * Frees the resources used by this object.
  203. * @private
  204. */
  205. VoxelContent.prototype.destroy = function () {
  206. this._loader = this._loader && this._loader.destroy();
  207. return destroyObject(this);
  208. };
  209. export default VoxelContent;