diff --git a/packages/engine/Source/Scene/Cesium3DTilesVoxelProvider.js b/packages/engine/Source/Scene/Cesium3DTilesVoxelProvider.js index 53235d9fb31..ee80f3b6d57 100644 --- a/packages/engine/Source/Scene/Cesium3DTilesVoxelProvider.js +++ b/packages/engine/Source/Scene/Cesium3DTilesVoxelProvider.js @@ -18,9 +18,9 @@ import Resource from "../Core/Resource.js"; import ResourceCache from "./ResourceCache.js"; import RuntimeError from "../Core/RuntimeError.js"; import VoxelBoxShape from "./VoxelBoxShape.js"; +import VoxelContent from "./VoxelContent.js"; import VoxelCylinderShape from "./VoxelCylinderShape.js"; import VoxelShapeType from "./VoxelShapeType.js"; -import VoxelContent from "./VoxelContent.js"; /** * A {@link VoxelProvider} that fetches voxel data from a 3D Tiles tileset. diff --git a/packages/engine/Source/Scene/KeyframeNode.js b/packages/engine/Source/Scene/KeyframeNode.js index cb5fb8e96bd..4b8ad648ab2 100644 --- a/packages/engine/Source/Scene/KeyframeNode.js +++ b/packages/engine/Source/Scene/KeyframeNode.js @@ -28,7 +28,6 @@ function KeyframeNode(spatialNode, keyframe) { /** * Frees the resources used by this object. - * TODO: replace with a destroy method? * @private */ KeyframeNode.prototype.unload = function () { diff --git a/packages/engine/Source/Scene/VoxelContent.js b/packages/engine/Source/Scene/VoxelContent.js index 70cf922c5e8..76d80560508 100644 --- a/packages/engine/Source/Scene/VoxelContent.js +++ b/packages/engine/Source/Scene/VoxelContent.js @@ -3,23 +3,17 @@ 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 getJsonFromTypedArray from "../Core/getJsonFromTypedArray.js"; import GltfLoader from "./GltfLoader.js"; import MetadataComponentType from "./MetadataComponentType.js"; -import MetadataTable from "./MetadataTable.js"; import MetadataType from "./MetadataType.js"; /** - *
- * To construct a VoxelContent, call {@link VoxelContent.fromGltf}. Do not call the constructor directly. - *
* An object representing voxel content for a {@link Cesium3DTilesVoxelProvider}. * * @alias VoxelContent * @constructor * * @param {object} options An object with the following properties: - * @param {Resource} [options.resource] The resource for this voxel content. This is used for fetching external buffers as needed. * @param {ResourceLoader} [options.loader] The loader used to load the voxel content. * @param {TypedArray[]} [options.metadata] The metadata for this voxel content. * @@ -29,7 +23,7 @@ import MetadataType from "./MetadataType.js"; * @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy. */ function VoxelContent(options) { - const { resource, loader, metadata } = options; + const { loader, metadata } = options; //>>includeStart('debug', pragmas.debug); Check.typeOf.object("options", options); if (!defined(loader)) { @@ -42,10 +36,7 @@ function VoxelContent(options) { } //>>includeEnd('debug'); - // TODO: do we need resource? - this._resource = resource; this._loader = loader; - this._metadata = metadata; this._resourcesLoaded = false; this._ready = false; @@ -82,6 +73,12 @@ Object.defineProperties(VoxelContent.prototype, { }, }); +/** + * Constructs a VoxelContent from a glTF resource. + * + * @param {Resource} resource A Resource pointing to a glTF containing voxel content + * @returns {Promise} A promise that resolves to the voxel content + */ VoxelContent.fromGltf = async function (resource) { //>>includeStart('debug', pragmas.debug); Check.typeOf.object("resource", resource); @@ -104,7 +101,7 @@ VoxelContent.fromGltf = async function (resource) { throw error; } - return new VoxelContent({ resource, loader }); + return new VoxelContent({ loader }); }; /** @@ -129,20 +126,17 @@ VoxelContent.prototype.update = function (primitive, frameState) { } if (this._resourcesLoaded) { - // TODO: load to megatexture? const { attributes } = loader.components.scene.nodes[0].primitives[0]; this._metadata = processAttributes(attributes, primitive); this._ready = true; return; } - // TODO: handle errors from GltfLoader.prototype.process this._resourcesLoaded = loader.process(frameState); }; /** * Processes the attributes from the glTF loader, reordering them into the order expected by the primitive. - * TODO: use a MetadataTable? * * @param {ModelComponents.Attribute[]} attributes The attributes to process * @param {VoxelPrimitive} primitive The primitive for which this voxel content will be used. @@ -150,8 +144,6 @@ VoxelContent.prototype.update = function (primitive, frameState) { * @private */ function processAttributes(attributes, primitive) { - //function processAttributes(attributes, primitive) { - //const { names, types, componentTypes } = primitive.provider; const { names, types, componentTypes } = primitive.provider; const data = new Array(attributes.length); @@ -182,131 +174,6 @@ function processAttributes(attributes, primitive) { return data; } -/** - * Creates an object representing voxel content for a {@link Cesium3DTilesVoxelProvider}. - * - * @param {Resource} resource The resource for this voxel content. This is used for fetching external buffers as needed. - * @param {object} [json] Voxel JSON contents. Mutually exclusive with binary. - * @param {Uint8Array} [binary] Voxel binary contents. Mutually exclusive with json. - * @param {MetadataSchema} metadataSchema The metadata schema used by property tables in the voxel content - * @returns {Promise} - * - * @exception {DeveloperError} One of json and binary must be defined. - */ -VoxelContent.fromJson = async function ( - resource, - json, - binary, - metadataSchema, -) { - //>>includeStart('debug', pragmas.debug); - Check.typeOf.object("resource", resource); - if (defined(json) === defined(binary)) { - throw new DeveloperError("One of json and binary must be defined."); - } - //>>includeEnd('debug'); - - let chunks; - if (defined(json)) { - chunks = { - json: json, - binary: undefined, - }; - } else { - chunks = parseVoxelChunks(binary); - } - - const buffersU8 = await requestBuffers(resource, chunks.json, chunks.binary); - const bufferViewsU8 = {}; - const bufferViewsLength = chunks.json.bufferViews.length; - for (let i = 0; i < bufferViewsLength; ++i) { - const bufferViewJson = chunks.json.bufferViews[i]; - const start = bufferViewJson.byteOffset; - const end = start + bufferViewJson.byteLength; - const buffer = buffersU8[bufferViewJson.buffer]; - const bufferView = buffer.subarray(start, end); - bufferViewsU8[i] = bufferView; - } - - const propertyTableIndex = chunks.json.voxelTable; - const propertyTableJson = chunks.json.propertyTables[propertyTableIndex]; - - const content = new VoxelContent(resource); - - content._metadataTable = new MetadataTable({ - count: propertyTableJson.count, - properties: propertyTableJson.properties, - class: metadataSchema.classes[propertyTableJson.class], - bufferViews: bufferViewsU8, - }); - - return content; -}; - -function requestBuffers(resource, json, binary) { - const buffersLength = json.buffers.length; - const bufferPromises = new Array(buffersLength); - for (let i = 0; i < buffersLength; i++) { - const buffer = json.buffers[i]; - if (defined(buffer.uri)) { - const baseResource = resource; - const bufferResource = baseResource.getDerivedResource({ - url: buffer.uri, - }); - bufferPromises[i] = bufferResource - .fetchArrayBuffer() - .then(function (arrayBuffer) { - return new Uint8Array(arrayBuffer); - }); - } else { - bufferPromises[i] = Promise.resolve(binary); - } - } - - return Promise.all(bufferPromises); -} - -/** - * A helper object for storing the two parts of the binary voxel content - * - * @typedef {object} VoxelChunks - * @property {object} json The json chunk of the binary voxel content - * @property {Uint8Array} binary The binary chunk of the binary voxel content. This represents the internal buffer. - * @private - */ - -/** - * Given binary voxel content, split into JSON and binary chunks - * - * @param {Uint8Array} binaryView The binary voxel content - * @returns {VoxelChunks} An object containing the JSON and binary chunks - * @private - */ -function parseVoxelChunks(binaryView) { - // Parse the header - const littleEndian = true; - const reader = new DataView(binaryView.buffer, binaryView.byteOffset); - // Skip to the chunk lengths - let byteOffset = 8; - - // Read the bottom 32 bits of the 64-bit byte length. This is ok for now because: - // 1) not all browsers have native 64-bit operations - // 2) the data is well under 4GB - const jsonByteLength = reader.getUint32(byteOffset, littleEndian); - byteOffset += 8; - const binaryByteLength = reader.getUint32(byteOffset, littleEndian); - byteOffset += 8; - - const json = getJsonFromTypedArray(binaryView, byteOffset, jsonByteLength); - byteOffset += jsonByteLength; - const binary = binaryView.subarray(byteOffset, byteOffset + binaryByteLength); - - return { - json: json, - binary: binary, - }; -} - /** * Returns true if this object was destroyed; otherwise, false. *

diff --git a/packages/engine/Source/Scene/VoxelPrimitive.js b/packages/engine/Source/Scene/VoxelPrimitive.js index 0942fbb817a..a4963175789 100644 --- a/packages/engine/Source/Scene/VoxelPrimitive.js +++ b/packages/engine/Source/Scene/VoxelPrimitive.js @@ -2,29 +2,30 @@ import buildVoxelDrawCommands from "./buildVoxelDrawCommands.js"; import Cartesian2 from "../Core/Cartesian2.js"; import Cartesian3 from "../Core/Cartesian3.js"; import Cartesian4 from "../Core/Cartesian4.js"; +import Cartographic from "../Core/Cartographic.js"; import CesiumMath from "../Core/Math.js"; import Check from "../Core/Check.js"; -import clone from "../Core/clone.js"; import Color from "../Core/Color.js"; +import ClippingPlaneCollection from "./ClippingPlaneCollection.js"; +import clone from "../Core/clone.js"; +import CustomShader from "./Model/CustomShader.js"; import defaultValue from "../Core/defaultValue.js"; import defined from "../Core/defined.js"; import destroyObject from "../Core/destroyObject.js"; +import Ellipsoid from "../Core/Ellipsoid.js"; import Event from "../Core/Event.js"; import JulianDate from "../Core/JulianDate.js"; +import Material from "./Material.js"; import Matrix3 from "../Core/Matrix3.js"; import Matrix4 from "../Core/Matrix4.js"; -import oneTimeWarning from "../Core/oneTimeWarning.js"; -import ClippingPlaneCollection from "./ClippingPlaneCollection.js"; -import Material from "./Material.js"; import MetadataComponentType from "./MetadataComponentType.js"; import MetadataType from "./MetadataType.js"; +import oneTimeWarning from "../Core/oneTimeWarning.js"; import PolylineCollection from "./PolylineCollection.js"; +import VerticalExaggeration from "../Core/VerticalExaggeration.js"; +import VoxelContent from "./VoxelContent.js"; import VoxelShapeType from "./VoxelShapeType.js"; import VoxelTraversal from "./VoxelTraversal.js"; -import CustomShader from "./Model/CustomShader.js"; -import Cartographic from "../Core/Cartographic.js"; -import Ellipsoid from "../Core/Ellipsoid.js"; -import VerticalExaggeration from "../Core/VerticalExaggeration.js"; /** * A primitive that renders voxel data from a {@link VoxelProvider}. @@ -1955,7 +1956,8 @@ DefaultVoxelProvider.prototype.requestData = function (options) { return undefined; } - return Promise.resolve([new Float32Array(1)]); + const content = new VoxelContent({ metadata: [new Float32Array(1)] }); + return Promise.resolve(content); }; VoxelPrimitive.DefaultProvider = new DefaultVoxelProvider(); diff --git a/packages/engine/Source/Scene/VoxelTraversal.js b/packages/engine/Source/Scene/VoxelTraversal.js index 9d7c9bcd553..bddc3321067 100644 --- a/packages/engine/Source/Scene/VoxelTraversal.js +++ b/packages/engine/Source/Scene/VoxelTraversal.js @@ -43,7 +43,6 @@ function VoxelTraversal( maximumTextureMemoryByteLength, ) { /** - * TODO: maybe this shouldn't be stored or passed into update function? * @type {VoxelPrimitive} * @private */ @@ -550,7 +549,6 @@ function updateKeyframeNodes(that, frameState) { continue; } if (!validateMetadata(content.metadata, that)) { - // TODO should this throw runtime error? highPriorityKeyframeNode.content = undefined; highPriorityKeyframeNode.state = KeyframeNode.LoadState.FAILED; continue;