| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- import { destroyObject } from "@cesium/engine";
- import Check from "../Core/Check.js";
- import ComponentDatatype from "../Core/ComponentDatatype.js";
- import DeveloperError from "../Core/DeveloperError.js";
- import defined from "../Core/defined.js";
- import GltfLoader from "./GltfLoader.js";
- import MetadataComponentType from "./MetadataComponentType.js";
- import MetadataType from "./MetadataType.js";
-
- /**
- * <div class="notice">
- * To construct a VoxelContent, call {@link VoxelContent.fromMetadataArray} or {@link VoxelContent.fromGltf}. Do not call the constructor directly.
- * </div>
- * An object representing voxel content for a {@link Cesium3DTilesVoxelProvider}.
- *
- * @alias VoxelContent
- * @internalConstructor
- *
- * @privateParam {object} options An object with the following properties:
- * @privateParam {ResourceLoader} [options.loader] The loader used to load the voxel content.
- * @privateParam {Int8Array[]|Uint8Array[]|Int16Array[]|Uint16Array[]|Int32Array[]|Uint32Array[]|Float32Array[]|Float64Array[]} [options.metadata] The metadata for this voxel content.
- *
- * @exception {DeveloperError} One of loader and metadata must be defined.
- * @exception {DeveloperError} metadata must be an array of TypedArrays.
- *
- * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
- */
- function VoxelContent(options) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("options", options);
- if (!defined(options.loader)) {
- if (!defined(options.metadata)) {
- throw new DeveloperError("One of loader and metadata must be defined.");
- }
- if (!Array.isArray(options.metadata)) {
- throw new DeveloperError("metadata must be an array of TypedArrays.");
- }
- }
- //>>includeEnd('debug');
-
- const { loader, metadata } = options;
-
- this._loader = loader;
- this._metadata = metadata;
- this._resourcesLoaded = false;
- this._ready = false;
- }
-
- Object.defineProperties(VoxelContent.prototype, {
- /**
- * Returns true when the content is ready to render; otherwise false
- *
- * @memberof VoxelContent.prototype
- *
- * @type {boolean}
- * @readonly
- * @private
- */
- ready: {
- get: function () {
- return this._ready;
- },
- },
-
- /**
- * The metadata for this voxel content.
- * The metadata is an array of typed arrays, one for each field.
- * The data for one field is a flattened 3D array ordered by X, then Y, then Z.
- *
- * @memberof VoxelContent.prototype
- * @type {Int8Array[]|Uint8Array[]|Int16Array[]|Uint16Array[]|Int32Array[]|Uint32Array[]|Float32Array[]|Float64Array[]}
- * @readonly
- */
- metadata: {
- get: function () {
- return this._metadata;
- },
- },
- });
-
- /**
- * Constructs a VoxelContent from an array of metadata.
- *
- * @param {Int8Array[]|Uint8Array[]|Int16Array[]|Uint16Array[]|Int32Array[]|Uint32Array[]|Float32Array[]|Float64Array[]} metadata The metadata to use for this voxel content.
- * @returns {VoxelContent} A VoxelContent containing the specified metadata.
- */
- VoxelContent.fromMetadataArray = function (metadata) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("metadata", metadata);
- if (!Array.isArray(metadata)) {
- throw new DeveloperError("metadata must be an array of TypedArrays.");
- }
- //>>includeEnd('debug');
-
- return new VoxelContent({ metadata });
- };
-
- /**
- * Constructs a VoxelContent from a glTF resource.
- *
- * @param {Resource} resource A Resource pointing to a glTF containing voxel content.
- * @returns {Promise<VoxelContent>} A promise that resolves to the voxel content.
- *
- * @private
- */
- VoxelContent.fromGltf = async function (resource) {
- //>>includeStart('debug', pragmas.debug);
- Check.typeOf.object("resource", resource);
- //>>includeEnd('debug');
-
- // Construct the glTF loader
- const loader = new GltfLoader({
- gltfResource: resource,
- releaseGltfJson: false,
- loadAttributesAsTypedArray: true,
- });
-
- try {
- // This loads the gltf JSON and ensures the gltf is valid
- // Further resource loading is handled synchronously in loader.process()
- // via voxelContent.update() as the frameState is needed
- await loader.load();
- } catch (error) {
- loader.destroy();
- throw error;
- }
-
- return new VoxelContent({ loader });
- };
-
- /**
- * Updates the content until all resources are ready for rendering.
- * @param {FrameState} frameState The frame state
- * @private
- */
- VoxelContent.prototype.update = function (primitive, frameState) {
- const loader = this._loader;
-
- if (this._ready) {
- // Nothing to do
- return;
- }
-
- // Ensures frames continue to render in requestRender mode while resources are processing
- frameState.afterRender.push(() => true);
-
- if (!defined(loader)) {
- this._ready = true;
- return;
- }
-
- if (this._resourcesLoaded) {
- const { structuralMetadata, scene } = loader.components;
- const { attributes } = scene.nodes[0].primitives[0];
- this._metadata = processAttributes(
- attributes,
- structuralMetadata,
- primitive,
- );
- this._ready = true;
- return;
- }
-
- this._resourcesLoaded = loader.process(frameState);
- };
-
- /**
- * Processes the attributes from the glTF loader, reordering them into the order expected by the primitive.
- *
- * @param {ModelComponents.Attribute[]} attributes The attributes to process
- * @param {StructuralMetadata} structuralMetadata Information from the glTF EXT_structural_metadata extension
- * @param {VoxelPrimitive} primitive The primitive for which this voxel content will be used.
- * @returns {Int8Array[]|Uint8Array[]|Int16Array[]|Uint16Array[]|Int32Array[]|Uint32Array[]|Float32Array[]|Float64Array[]} An array of typed arrays containing the attribute values
- * @private
- */
- function processAttributes(attributes, structuralMetadata, primitive) {
- const { className, names, types, componentTypes } = primitive.provider;
- const propertyAttribute = structuralMetadata.propertyAttributes.find(
- (p) => p.class.id === className,
- );
- const { properties } = propertyAttribute;
- const data = new Array(names.length);
-
- for (let i = 0; i < attributes.length; i++) {
- // Find the appropriate glTF attribute based on its name.
- const name = properties[names[i]].attribute;
- const attribute = attributes.find((a) => a.name === name);
- if (!defined(attribute)) {
- continue;
- }
-
- const componentDatatype = MetadataComponentType.toComponentDatatype(
- componentTypes[i],
- );
- const componentCount = MetadataType.getComponentCount(types[i]);
- const totalCount = attribute.count * componentCount;
- data[i] = ComponentDatatype.createArrayBufferView(
- componentDatatype,
- attribute.typedArray.buffer,
- attribute.typedArray.byteOffset + attribute.byteOffset,
- totalCount,
- );
- }
-
- return data;
- }
-
- /**
- * Returns true if this object was destroyed; otherwise, false.
- * <br /><br />
- * If this object was destroyed, it should not be used; calling any function other than
- * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
- *
- * @returns {boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
- *
- * @see VoxelContent#destroy
- *
- * @private
- */
- VoxelContent.prototype.isDestroyed = function () {
- return false;
- };
-
- /**
- * Frees the resources used by this object.
- * @private
- */
- VoxelContent.prototype.destroy = function () {
- this._loader = this._loader && this._loader.destroy();
- return destroyObject(this);
- };
-
- export default VoxelContent;
|