From 225685956cd9734bcb1ed6e7c0fd847f042e85b4 Mon Sep 17 00:00:00 2001 From: gdiehlEB Date: Mon, 18 Dec 2023 16:55:32 -0500 Subject: [PATCH 1/3] add heightReference and scene options for vector 3d tiles --- packages/engine/Source/Scene/Cesium3DTile.js | 3 +- .../Scene/Cesium3DTileContentFactory.js | 5 ++- .../engine/Source/Scene/Cesium3DTileset.js | 40 +++++++++++++++++++ .../Source/Scene/Vector3DTileContent.js | 18 ++++++--- .../engine/Source/Scene/Vector3DTilePoints.js | 10 +++++ 5 files changed, 68 insertions(+), 8 deletions(-) diff --git a/packages/engine/Source/Scene/Cesium3DTile.js b/packages/engine/Source/Scene/Cesium3DTile.js index 86efbeec1cf9..f59117829865 100644 --- a/packages/engine/Source/Scene/Cesium3DTile.js +++ b/packages/engine/Source/Scene/Cesium3DTile.js @@ -1348,7 +1348,8 @@ async function makeContent(tile, arrayBuffer) { tile, tile._contentResource, preprocessed.binaryPayload.buffer, - 0 + 0, + tileset.scene ) ); } else { diff --git a/packages/engine/Source/Scene/Cesium3DTileContentFactory.js b/packages/engine/Source/Scene/Cesium3DTileContentFactory.js index 281235e37778..dc020196f406 100644 --- a/packages/engine/Source/Scene/Cesium3DTileContentFactory.js +++ b/packages/engine/Source/Scene/Cesium3DTileContentFactory.js @@ -62,13 +62,14 @@ const Cesium3DTileContentFactory = { byteOffset ); }, - vctr: function (tileset, tile, resource, arrayBuffer, byteOffset) { + vctr: function (tileset, tile, resource, arrayBuffer, byteOffset, scene) { return new Vector3DTileContent( tileset, tile, resource, arrayBuffer, - byteOffset + byteOffset, + scene ); }, subt: function (tileset, tile, resource, arrayBuffer, byteOffset) { diff --git a/packages/engine/Source/Scene/Cesium3DTileset.js b/packages/engine/Source/Scene/Cesium3DTileset.js index 0f5f3b56bcb9..73383bb0179e 100644 --- a/packages/engine/Source/Scene/Cesium3DTileset.js +++ b/packages/engine/Source/Scene/Cesium3DTileset.js @@ -93,6 +93,8 @@ import Cesium3DTilesetSkipTraversal from "./Cesium3DTilesetSkipTraversal.js"; * @property {boolean} [loadSiblings=false] When skipLevelOfDetail is true, determines whether siblings of visible tiles are always downloaded during traversal. * @property {ClippingPlaneCollection} [clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the tileset. * @property {ClassificationType} [classificationType] Determines whether terrain, 3D Tiles or both will be classified by this tileset. See {@link Cesium3DTileset#classificationType} for details about restrictions and limitations. + * @property {HeightReference} [heightReference] Sets the {@link HeightReference} for point features in vector tilesets. + * @property {Scene} [scene] The {@link CesiumWidget#scene}. This is required for clamping billboards and labels of point features with {@link HeightReference}. * @property {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid determining the size and shape of the globe. * @property {object} [pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation based on geometric error and lighting. * @property {Cartesian3} [lightColor] The light color when shading models. When undefined the scene's light color is used instead. @@ -323,6 +325,8 @@ function Cesium3DTileset(options) { this._tileDebugLabels = undefined; this._classificationType = options.classificationType; + this._heightReference = options.heightReference; + this._scene = options.scene; this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); @@ -1659,6 +1663,42 @@ Object.defineProperties(Cesium3DTileset.prototype, { }, }, + /** + * A Property specifying if the height is relative to terrain, 3D Tiles, or both. + *

+ * This option is only applied to point features in tilesets containing vector data. + * This option requires the Viewer's scene to be passed in through options.scene. + *

+ * + * @memberof Cesium3DTileset.prototype + * + * @type {HeightReference} + * @default undefined + * + * @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. + * @readonly + */ + heightReference: { + get: function () { + return this._heightReference; + }, + }, + + /** + * The CesiumWidget scene, used with heightReference for clamping vector tile points to terrain or 3D tiles. + * + * @member of Cesium3DTileset.prototype + * + * @type {Scene} + * @readonly + * + */ + scene: { + get: function () { + return this._scene; + }, + }, + /** * Gets an ellipsoid describing the shape of the globe. * diff --git a/packages/engine/Source/Scene/Vector3DTileContent.js b/packages/engine/Source/Scene/Vector3DTileContent.js index e191ede706a9..a22e12c9afbd 100644 --- a/packages/engine/Source/Scene/Vector3DTileContent.js +++ b/packages/engine/Source/Scene/Vector3DTileContent.js @@ -31,7 +31,14 @@ import decodeVectorPolylinePositions from "../Core/decodeVectorPolylinePositions * * @private */ -function Vector3DTileContent(tileset, tile, resource, arrayBuffer, byteOffset) { +function Vector3DTileContent( + tileset, + tile, + resource, + arrayBuffer, + byteOffset, + scene +) { this._tileset = tileset; this._tile = tile; this._resource = resource; @@ -53,7 +60,7 @@ function Vector3DTileContent(tileset, tile, resource, arrayBuffer, byteOffset) { this._ready = false; - initialize(this, arrayBuffer, byteOffset); + initialize(this, arrayBuffer, byteOffset, scene); } Object.defineProperties(Vector3DTileContent.prototype, { @@ -288,7 +295,7 @@ function createClampedPolylines(options) { return new Vector3DTileClampedPolylines(options); } -function initialize(content, arrayBuffer, byteOffset) { +function initialize(content, arrayBuffer, byteOffset, scene) { byteOffset = defaultValue(byteOffset, 0); const uint8Array = new Uint8Array(arrayBuffer); @@ -528,7 +535,7 @@ function initialize(content, arrayBuffer, byteOffset) { modelMatrix: modelMatrix, }); } - + const tileset = content._tileset; if (numberOfPolylines > 0) { featureTable.featuresLength = numberOfPolylines; @@ -575,7 +582,6 @@ function initialize(content, arrayBuffer, byteOffset) { ); byteOffset += polylinePositionByteLength; - const tileset = content._tileset; const examineVectorLinesFunction = tileset.examineVectorLinesFunction; if (defined(examineVectorLinesFunction)) { const decodedPositions = decodeVectorPolylinePositions( @@ -630,6 +636,8 @@ function initialize(content, arrayBuffer, byteOffset) { maximumHeight: maxHeight, rectangle: rectangle, batchTable: batchTable, + heightReference: tileset.heightReference, + scene: scene, }); } } diff --git a/packages/engine/Source/Scene/Vector3DTilePoints.js b/packages/engine/Source/Scene/Vector3DTilePoints.js index 7bea9c2c9022..94848095f39a 100644 --- a/packages/engine/Source/Scene/Vector3DTilePoints.js +++ b/packages/engine/Source/Scene/Vector3DTilePoints.js @@ -15,6 +15,7 @@ import LabelCollection from "./LabelCollection.js"; import LabelStyle from "./LabelStyle.js"; import PolylineCollection from "./PolylineCollection.js"; import VerticalOrigin from "./VerticalOrigin.js"; +import HeightReference from "./HeightReference.js"; /** * Creates a batch of points or billboards and labels. @@ -27,8 +28,10 @@ import VerticalOrigin from "./VerticalOrigin.js"; * @param {number} options.minimumHeight The minimum height of the terrain covered by the tile. * @param {number} options.maximumHeight The maximum height of the terrain covered by the tile. * @param {Rectangle} options.rectangle The rectangle containing the tile. + * @param {HeightReference} options.heightReference The height reference of the tile. * @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched polygons. * @param {Uint16Array} options.batchIds The batch ids for each polygon. + * @param {Scene} options.scene The Cesium Viewer {@link Scene}. This is required for clamping billboards and labels with {@link HeightReference} * * @private */ @@ -42,12 +45,15 @@ function Vector3DTilePoints(options) { this._rectangle = options.rectangle; this._minHeight = options.minimumHeight; this._maxHeight = options.maximumHeight; + this._heightReference = options.heightReference; this._billboardCollection = new BillboardCollection({ batchTable: options.batchTable, + scene: options.scene, }); this._labelCollection = new LabelCollection({ batchTable: options.batchTable, + scene: options.scene, }); this._polylineCollection = new PolylineCollection(); this._polylineCollection._useHighlightColor = true; @@ -176,6 +182,8 @@ function createPoints(points, ellipsoid) { const batchIds = points._batchIds; const numberOfPoints = positions.length / 3; + const heightReference = points._heightReference ?? HeightReference.NONE; + for (let i = 0; i < numberOfPoints; ++i) { const id = batchIds[i]; @@ -184,11 +192,13 @@ function createPoints(points, ellipsoid) { const b = billboardCollection.add(); b.position = position; b._batchIndex = id; + b.heightReference = heightReference; const l = labelCollection.add(); l.text = " "; l.position = position; l._batchIndex = id; + l.heightReference = heightReference; const p = polylineCollection.add(); p.positions = [Cartesian3.clone(position), Cartesian3.clone(position)]; From a81ac48f7c788891028166e9b4a0f6dfae196b6a Mon Sep 17 00:00:00 2001 From: gdiehlEB Date: Thu, 11 Jan 2024 11:21:18 -0500 Subject: [PATCH 2/3] code cleanup: access scene via tileset --- packages/engine/Source/Scene/Cesium3DTile.js | 3 +-- .../engine/Source/Scene/Cesium3DTileContentFactory.js | 5 ++--- packages/engine/Source/Scene/Vector3DTileContent.js | 11 ++--------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/packages/engine/Source/Scene/Cesium3DTile.js b/packages/engine/Source/Scene/Cesium3DTile.js index f59117829865..86efbeec1cf9 100644 --- a/packages/engine/Source/Scene/Cesium3DTile.js +++ b/packages/engine/Source/Scene/Cesium3DTile.js @@ -1348,8 +1348,7 @@ async function makeContent(tile, arrayBuffer) { tile, tile._contentResource, preprocessed.binaryPayload.buffer, - 0, - tileset.scene + 0 ) ); } else { diff --git a/packages/engine/Source/Scene/Cesium3DTileContentFactory.js b/packages/engine/Source/Scene/Cesium3DTileContentFactory.js index dc020196f406..281235e37778 100644 --- a/packages/engine/Source/Scene/Cesium3DTileContentFactory.js +++ b/packages/engine/Source/Scene/Cesium3DTileContentFactory.js @@ -62,14 +62,13 @@ const Cesium3DTileContentFactory = { byteOffset ); }, - vctr: function (tileset, tile, resource, arrayBuffer, byteOffset, scene) { + vctr: function (tileset, tile, resource, arrayBuffer, byteOffset) { return new Vector3DTileContent( tileset, tile, resource, arrayBuffer, - byteOffset, - scene + byteOffset ); }, subt: function (tileset, tile, resource, arrayBuffer, byteOffset) { diff --git a/packages/engine/Source/Scene/Vector3DTileContent.js b/packages/engine/Source/Scene/Vector3DTileContent.js index a22e12c9afbd..f5d22672abc7 100644 --- a/packages/engine/Source/Scene/Vector3DTileContent.js +++ b/packages/engine/Source/Scene/Vector3DTileContent.js @@ -31,14 +31,7 @@ import decodeVectorPolylinePositions from "../Core/decodeVectorPolylinePositions * * @private */ -function Vector3DTileContent( - tileset, - tile, - resource, - arrayBuffer, - byteOffset, - scene -) { +function Vector3DTileContent(tileset, tile, resource, arrayBuffer, byteOffset) { this._tileset = tileset; this._tile = tile; this._resource = resource; @@ -60,7 +53,7 @@ function Vector3DTileContent( this._ready = false; - initialize(this, arrayBuffer, byteOffset, scene); + initialize(this, arrayBuffer, byteOffset, tileset.scene); } Object.defineProperties(Vector3DTileContent.prototype, { From c4930eefe016a5ee8075cd73300c7b08ba47e36f Mon Sep 17 00:00:00 2001 From: gdiehlEB Date: Tue, 26 Mar 2024 17:37:28 -0400 Subject: [PATCH 3/3] specs and docs cleanup --- .../engine/Source/Scene/Cesium3DTileset.js | 2 +- .../engine/Source/Scene/Vector3DTilePoints.js | 2 +- .../Specs/Scene/Vector3DTileContentSpec.js | 14 +++++ .../Specs/Scene/Vector3DTilePointsSpec.js | 58 +++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/packages/engine/Source/Scene/Cesium3DTileset.js b/packages/engine/Source/Scene/Cesium3DTileset.js index 5ee2b1b15014..061fd8736c03 100644 --- a/packages/engine/Source/Scene/Cesium3DTileset.js +++ b/packages/engine/Source/Scene/Cesium3DTileset.js @@ -99,7 +99,7 @@ import Ray from "../Core/Ray.js"; * @property {ClippingPlaneCollection} [clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the tileset. * @property {ClassificationType} [classificationType] Determines whether terrain, 3D Tiles or both will be classified by this tileset. See {@link Cesium3DTileset#classificationType} for details about restrictions and limitations. * @property {HeightReference} [heightReference] Sets the {@link HeightReference} for point features in vector tilesets. - * @property {Scene} [scene] The {@link CesiumWidget#scene}. This is required for clamping billboards and labels of point features with {@link HeightReference}. + * @property {Scene} [scene] The {@link CesiumWidget#scene}. Must be passed in for tilesets that use {@link HeightReference} to clamp billboards and labels of vector tiles. * @property {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid determining the size and shape of the globe. * @property {object} [pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation based on geometric error and lighting. * @property {Cartesian3} [lightColor] The light color when shading models. When undefined the scene's light color is used instead. diff --git a/packages/engine/Source/Scene/Vector3DTilePoints.js b/packages/engine/Source/Scene/Vector3DTilePoints.js index 94848095f39a..ce08d5bc63e9 100644 --- a/packages/engine/Source/Scene/Vector3DTilePoints.js +++ b/packages/engine/Source/Scene/Vector3DTilePoints.js @@ -28,7 +28,7 @@ import HeightReference from "./HeightReference.js"; * @param {number} options.minimumHeight The minimum height of the terrain covered by the tile. * @param {number} options.maximumHeight The maximum height of the terrain covered by the tile. * @param {Rectangle} options.rectangle The rectangle containing the tile. - * @param {HeightReference} options.heightReference The height reference of the tile. + * @param {HeightReference} options.heightReference Determines how billboard and label features are positioned relative to terrain or 3d tiles. * @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched polygons. * @param {Uint16Array} options.batchIds The batch ids for each polygon. * @param {Scene} options.scene The Cesium Viewer {@link Scene}. This is required for clamping billboards and labels with {@link HeightReference} diff --git a/packages/engine/Specs/Scene/Vector3DTileContentSpec.js b/packages/engine/Specs/Scene/Vector3DTileContentSpec.js index 4106b41aa0ed..03bfabc22ec7 100644 --- a/packages/engine/Specs/Scene/Vector3DTileContentSpec.js +++ b/packages/engine/Specs/Scene/Vector3DTileContentSpec.js @@ -7,6 +7,7 @@ import { Cesium3DTileset, Cesium3DTileStyle, ClassificationType, + HeightReference, Color, ColorGeometryInstanceAttribute, destroyObject, @@ -622,6 +623,19 @@ describe( expect(scene).toRender(whitePixel); }); }); + + it("sets the heightReference for Vector3DTilePoints", () => { + const heightReference = HeightReference.CLAMP_TO_3D_TILE; + return Cesium3DTilesTester.loadTileset(scene, vectorTilePointsTileset, { + heightReference: heightReference, + scene, + }).then((tileset) => { + const vectorTile = tileset._root.children[0]; + const vectorTilePoint = vectorTile._content._points; + + expect(vectorTilePoint._heightReference).toEqual(heightReference); + }); + }); }); describe("polygons", () => { diff --git a/packages/engine/Specs/Scene/Vector3DTilePointsSpec.js b/packages/engine/Specs/Scene/Vector3DTilePointsSpec.js index c1a22dfedf69..d583024d564f 100644 --- a/packages/engine/Specs/Scene/Vector3DTilePointsSpec.js +++ b/packages/engine/Specs/Scene/Vector3DTilePointsSpec.js @@ -8,6 +8,7 @@ import { defined, DistanceDisplayCondition, Ellipsoid, + HeightReference, NearFarScalar, Rectangle, Cesium3DTileBatchTable, @@ -579,6 +580,7 @@ describe( maxHeight, cartoPositions ); + const heightReference = HeightReference.CLAMP_TO_TERRAIN; const batchTable = new Cesium3DTileBatchTable(mockTileset, 1); batchTable.update(mockTileset, scene.frameState); @@ -591,6 +593,8 @@ describe( rectangle: rectangle, minimumHeight: minHeight, maximumHeight: maxHeight, + heightReference: heightReference, + scene, }) ); @@ -618,10 +622,64 @@ describe( }).then(function () { expect(billboard.ready).toEqual(true); expect(scene).toRender([0, 0, 255, 255]); + expect(billboard.heightReference).toEqual(heightReference); }); }); }); + it("renders a point with a label", function () { + const minHeight = 0.0; + const maxHeight = 100.0; + const cartoPositions = [Cartographic.fromDegrees(0.0, 0.0, 10.0)]; + const positions = encodePositions( + rectangle, + minHeight, + maxHeight, + cartoPositions + ); + const heightReference = HeightReference.CLAMP_TO_TERRAIN; + + const batchTable = new Cesium3DTileBatchTable(mockTileset, 1); + batchTable.update(mockTileset, scene.frameState); + + points = scene.primitives.add( + new Vector3DTilePoints({ + positions: positions, + batchTable: batchTable, + batchIds: new Uint16Array([0]), + rectangle: rectangle, + minimumHeight: minHeight, + maximumHeight: maxHeight, + heightReference: heightReference, + scene, + }) + ); + + const style = new Cesium3DTileStyle({ + labelText: '"test"', + labelColor: "rgba(100, 255, 0, 255)", + labelHorizontalOrigin: HorizontalOrigin.LEFT, + }); + return loadPoints(points).then(function () { + const features = []; + points.createFeatures(mockTileset, features); + points.applyStyle(style, features); + + const collection = points._labelCollection; + expect(collection.length).toEqual(1); + const label = collection.get(0); + expect(label).toBeDefined(); + + scene.camera.lookAt( + Cartesian3.fromDegrees(0.0, 0.0, 10.0), + new Cartesian3(0.0, 0.0, 50.0) + ); + + expect(scene).toRender([100, 255, 0, 255]); + expect(label.heightReference).toEqual(heightReference); + }); + }); + it("renders multiple points with debug color", function () { const minHeight = 0.0; const maxHeight = 100.0;