Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for clamping Vector 3D Tile point features to Terrain or 3d Tiles #11710

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions packages/engine/Source/Scene/Cesium3DTileset.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ import Ray from "../Core/Ray.js";
* @property {boolean} [loadSiblings=false] When <code>skipLevelOfDetail</code> is <code>true</code>, 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}. 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 <code>undefined</code> the scene's light color is used instead.
Expand Down Expand Up @@ -344,6 +346,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);

Expand Down Expand Up @@ -1712,6 +1716,42 @@ Object.defineProperties(Cesium3DTileset.prototype, {
},
},

/**
* A Property specifying if the height is relative to terrain, 3D Tiles, or both.
* <p>
* 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.
* </p>
*
* @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.
*
Expand Down
9 changes: 5 additions & 4 deletions packages/engine/Source/Scene/Vector3DTileContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function Vector3DTileContent(tileset, tile, resource, arrayBuffer, byteOffset) {

this._ready = false;

initialize(this, arrayBuffer, byteOffset);
initialize(this, arrayBuffer, byteOffset, tileset.scene);
}

Object.defineProperties(Vector3DTileContent.prototype, {
Expand Down Expand Up @@ -288,7 +288,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);
Expand Down Expand Up @@ -528,7 +528,7 @@ function initialize(content, arrayBuffer, byteOffset) {
modelMatrix: modelMatrix,
});
}

const tileset = content._tileset;
if (numberOfPolylines > 0) {
featureTable.featuresLength = numberOfPolylines;

Expand Down Expand Up @@ -575,7 +575,6 @@ function initialize(content, arrayBuffer, byteOffset) {
);
byteOffset += polylinePositionByteLength;

const tileset = content._tileset;
const examineVectorLinesFunction = tileset.examineVectorLinesFunction;
if (defined(examineVectorLinesFunction)) {
const decodedPositions = decodeVectorPolylinePositions(
Expand Down Expand Up @@ -630,6 +629,8 @@ function initialize(content, arrayBuffer, byteOffset) {
maximumHeight: maxHeight,
rectangle: rectangle,
batchTable: batchTable,
heightReference: tileset.heightReference,
scene: scene,
});
}
}
Expand Down
10 changes: 10 additions & 0 deletions packages/engine/Source/Scene/Vector3DTilePoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 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}
*
* @private
*/
Expand All @@ -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;
Expand Down Expand Up @@ -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];

Expand All @@ -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)];
Expand Down
14 changes: 14 additions & 0 deletions packages/engine/Specs/Scene/Vector3DTileContentSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Cesium3DTileset,
Cesium3DTileStyle,
ClassificationType,
HeightReference,
Color,
ColorGeometryInstanceAttribute,
destroyObject,
Expand Down Expand Up @@ -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", () => {
Expand Down
58 changes: 58 additions & 0 deletions packages/engine/Specs/Scene/Vector3DTilePointsSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
defined,
DistanceDisplayCondition,
Ellipsoid,
HeightReference,
NearFarScalar,
Rectangle,
Cesium3DTileBatchTable,
Expand Down Expand Up @@ -579,6 +580,7 @@ describe(
maxHeight,
cartoPositions
);
const heightReference = HeightReference.CLAMP_TO_TERRAIN;

const batchTable = new Cesium3DTileBatchTable(mockTileset, 1);
batchTable.update(mockTileset, scene.frameState);
Expand All @@ -591,6 +593,8 @@ describe(
rectangle: rectangle,
minimumHeight: minHeight,
maximumHeight: maxHeight,
heightReference: heightReference,
scene,
})
);

Expand Down Expand Up @@ -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;
Expand Down