Add existing to tracked
This commit is contained in:
+472
@@ -0,0 +1,472 @@
|
||||
// @ts-check
|
||||
|
||||
import BufferPoint from "./BufferPoint.js";
|
||||
import BufferPointCollection from "./BufferPointCollection.js";
|
||||
import BufferPointMaterial from "./BufferPointMaterial.js";
|
||||
import BufferPolygon from "./BufferPolygon.js";
|
||||
import BufferPolygonCollection from "./BufferPolygonCollection.js";
|
||||
import BufferPolygonMaterial from "./BufferPolygonMaterial.js";
|
||||
import BufferPolyline from "./BufferPolyline.js";
|
||||
import BufferPolylineCollection from "./BufferPolylineCollection.js";
|
||||
import BufferPolylineMaterial from "./BufferPolylineMaterial.js";
|
||||
import Cesium3DTileStyle from "./Cesium3DTileStyle.js";
|
||||
import Matrix4 from "../Core/Matrix4.js";
|
||||
import Model from "./Model/Model.js";
|
||||
import ModelUtility from "./Model/ModelUtility.js";
|
||||
import Pass from "../Renderer/Pass.js";
|
||||
import createVectorTileBuffersFromModelComponents from "./Model/createVectorTileBuffersFromModelComponents.js";
|
||||
import defined from "../Core/defined.js";
|
||||
import destroyObject from "../Core/destroyObject.js";
|
||||
import DeveloperError from "../Core/DeveloperError.js";
|
||||
import { isHeightReferenceClamp } from "./HeightReference.js";
|
||||
|
||||
/** @import BufferPrimitive from "./BufferPrimitive.js"; */
|
||||
/** @import BufferPrimitiveCollection from "./BufferPrimitiveCollection.js"; */
|
||||
/** @import Cartesian3 from "../Core/Cartesian3.js"; */
|
||||
/** @import Cesium3DContentGroup from "./Cesium3DContentGroup.js"; */
|
||||
/** @import Cesium3DTile from "./Cesium3DTile.js"; */
|
||||
/** @import Cesium3DTileBatchTable from "./Cesium3DTileBatchTable.js"; */
|
||||
/** @import Cesium3DTileVectorFeature from "./Cesium3DTileVectorFeature.js";*/
|
||||
/** @import Cesium3DTileset from "./Cesium3DTileset.js"; */
|
||||
/** @import Color from "../Core/Color.js"; */
|
||||
/** @import FrameState from "./FrameState.js"; */
|
||||
/** @import ImplicitMetadataView from "./ImplicitMetadataView.js"; */
|
||||
/** @import Ray from "../Core/Ray.js"; */
|
||||
/** @import Resource from "../Core/Resource.js"; */
|
||||
|
||||
/** @ignore */
|
||||
const point = new BufferPoint();
|
||||
/** @ignore */
|
||||
const polyline = new BufferPolyline();
|
||||
/** @ignore */
|
||||
const polygon = new BufferPolygon();
|
||||
|
||||
/** @ignore */
|
||||
const pointMaterial = new BufferPointMaterial();
|
||||
/** @ignore */
|
||||
const polylineMaterial = new BufferPolylineMaterial();
|
||||
/** @ignore */
|
||||
const polygonMaterial = new BufferPolygonMaterial();
|
||||
|
||||
/** @ignore */
|
||||
const scratchTileModelMatrix = new Matrix4();
|
||||
|
||||
/**
|
||||
* Vector glTF tile content. This path decodes glTF primitives into vector
|
||||
* buffers, then renders with dedicated vector primitives.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
class VectorGltf3DTileContent {
|
||||
/**
|
||||
* @param {Cesium3DTileset} tileset
|
||||
* @param {Cesium3DTile} tile
|
||||
* @param {Resource} resource
|
||||
*/
|
||||
constructor(tileset, tile, resource) {
|
||||
/** @type {Cesium3DTileset} */
|
||||
this._tileset = tileset;
|
||||
/** @type {Cesium3DTile} */
|
||||
this._tile = tile;
|
||||
/** @type {Resource} */
|
||||
this._resource = resource;
|
||||
|
||||
/** @type {Model} */
|
||||
this._model = undefined;
|
||||
|
||||
/**
|
||||
* List of all vector primitive collections.
|
||||
* @type {Array<BufferPrimitiveCollection<BufferPrimitive>>}
|
||||
*/
|
||||
this._collections = [];
|
||||
|
||||
/**
|
||||
* List of transform matrices for each collection; order matches 'collections'.
|
||||
* @type {Array<Matrix4>}
|
||||
*/
|
||||
this._collectionLocalMatrices = [];
|
||||
|
||||
/**
|
||||
* Maps vector primitive collection -> propertyTableId.
|
||||
* @type {Map<BufferPrimitiveCollection<BufferPrimitive>, number>}
|
||||
*/
|
||||
this._collectionFeatureTableIds = new Map();
|
||||
|
||||
/**
|
||||
* Maps propertyTableId -> featureId -> feature. Note that Feature IDs are
|
||||
* unique within their assigned property table, but not globally unique.
|
||||
* @type {Map<number, Map<number, Cesium3DTileVectorFeature>>}
|
||||
*/
|
||||
this._featuresByTableId = new Map();
|
||||
|
||||
/** @type {ImplicitMetadataView} */
|
||||
this._metadata = undefined;
|
||||
/** @type {Cesium3DContentGroup} */
|
||||
this._group = undefined;
|
||||
|
||||
/** @type {boolean} */
|
||||
this.featurePropertiesDirty = false;
|
||||
|
||||
/** @type {boolean} */
|
||||
this._ready = false;
|
||||
|
||||
/** @type {Matrix4} */
|
||||
this._modelMatrix = Matrix4.clone(Matrix4.IDENTITY);
|
||||
}
|
||||
|
||||
get featuresLength() {
|
||||
return this.batchTables.reduce(
|
||||
(acc, batchTable) => acc + batchTable.featuresLength,
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
get pointsLength() {
|
||||
return this._collections
|
||||
.filter((collection) => collection instanceof BufferPointCollection)
|
||||
.reduce((acc, collection) => acc + collection.primitiveCount, 0);
|
||||
}
|
||||
|
||||
get trianglesLength() {
|
||||
return this._collections.reduce((acc, collection) => {
|
||||
if (collection instanceof BufferPolygonCollection) {
|
||||
return acc + collection.triangleCount;
|
||||
} else if (collection instanceof BufferPolylineCollection) {
|
||||
return acc + (collection.vertexCount - collection.primitiveCount) * 2;
|
||||
}
|
||||
return acc;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
get geometryByteLength() {
|
||||
return this._collections.reduce((totalByteLength, collection) => {
|
||||
return totalByteLength + collection.byteLength;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
get texturesByteLength() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
get batchTableByteLength() {
|
||||
return this.batchTables.reduce(
|
||||
// @ts-expect-error Missing types.
|
||||
(acc, batchTable) => acc + batchTable.batchTableByteLength,
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
/** @returns {undefined} */
|
||||
get innerContents() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
get ready() {
|
||||
return this._ready;
|
||||
}
|
||||
|
||||
get tileset() {
|
||||
return this._tileset;
|
||||
}
|
||||
|
||||
get tile() {
|
||||
return this._tile;
|
||||
}
|
||||
|
||||
get url() {
|
||||
return this._resource.getUrlComponent(true);
|
||||
}
|
||||
|
||||
/** @type {Cesium3DTileBatchTable[]} */
|
||||
get batchTables() {
|
||||
return this._model._featureTables;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Cesium3DTileBatchTable}
|
||||
* @deprecated See {@link batchTables}.
|
||||
*/
|
||||
get batchTable() {
|
||||
throw new DeveloperError("Deprecated: Use `content.batchTables`.");
|
||||
}
|
||||
|
||||
/** @type {ImplicitMetadataView} */
|
||||
get metadata() {
|
||||
return this._metadata;
|
||||
}
|
||||
|
||||
set metadata(value) {
|
||||
this._metadata = value;
|
||||
}
|
||||
|
||||
/** @type {Cesium3DContentGroup} */
|
||||
get group() {
|
||||
return this._group;
|
||||
}
|
||||
|
||||
set group(value) {
|
||||
this._group = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} featureId
|
||||
* @param {number} [featureTableId]
|
||||
* @returns {Cesium3DTileVectorFeature}
|
||||
*/
|
||||
getFeature(featureId, featureTableId) {
|
||||
return this._featuresByTableId.get(featureTableId)?.get(featureId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} featureId
|
||||
* @param {string} name
|
||||
* @param {number} [featureTableId]
|
||||
* @returns {boolean}
|
||||
*/
|
||||
hasProperty(featureId, name, featureTableId) {
|
||||
const feature = this.getFeature(featureId, featureTableId);
|
||||
return feature ? feature.hasProperty(name) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} enabled
|
||||
* @param {Color} color
|
||||
*/
|
||||
applyDebugSettings(enabled, color) {
|
||||
const colorString = enabled
|
||||
? `color("${color.toCssHexString()}", 1.0)`
|
||||
: 'color("white", 1.0)';
|
||||
this.applyStyle(new Cesium3DTileStyle({ color: colorString }));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} style
|
||||
*/
|
||||
applyStyle(style) {
|
||||
const isPointCollection = /** @param {unknown} c */ (c) =>
|
||||
c instanceof BufferPointCollection;
|
||||
const isPolylineCollection = /** @param {unknown} c */ (c) =>
|
||||
c instanceof BufferPolylineCollection;
|
||||
const isPolygonCollection = /** @param {unknown} c */ (c) =>
|
||||
c instanceof BufferPolygonCollection;
|
||||
|
||||
for (const collection of this._collections.filter(isPointCollection)) {
|
||||
const featureTableId = this._collectionFeatureTableIds.get(collection);
|
||||
for (let i = 0, il = collection.primitiveCount; i < il; i++) {
|
||||
collection.get(i, point);
|
||||
const feature = this.getFeature(point.featureId, featureTableId);
|
||||
|
||||
if (defined(style.show)) {
|
||||
point.show = style.show.evaluate(feature);
|
||||
}
|
||||
if (defined(style.color)) {
|
||||
style.color.evaluate(feature, pointMaterial.color);
|
||||
}
|
||||
if (defined(style.pointSize)) {
|
||||
pointMaterial.size = style.pointSize.evaluate(feature);
|
||||
}
|
||||
if (defined(style.pointOutlineWidth)) {
|
||||
pointMaterial.outlineWidth =
|
||||
style.pointOutlineWidth.evaluate(feature);
|
||||
}
|
||||
if (defined(style.pointOutlineColor)) {
|
||||
style.pointOutlineColor.evaluate(feature, pointMaterial.outlineColor);
|
||||
}
|
||||
|
||||
point.setMaterial(pointMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
for (const collection of this._collections.filter(isPolylineCollection)) {
|
||||
const featureTableId = this._collectionFeatureTableIds.get(collection);
|
||||
for (let i = 0, il = collection.primitiveCount; i < il; i++) {
|
||||
collection.get(i, polyline);
|
||||
const feature = this.getFeature(polyline.featureId, featureTableId);
|
||||
|
||||
if (defined(style.show)) {
|
||||
polyline.show = style.show.evaluate(feature);
|
||||
}
|
||||
if (defined(style.color)) {
|
||||
style.color.evaluate(feature, polylineMaterial.color);
|
||||
}
|
||||
if (defined(style.lineWidth)) {
|
||||
polylineMaterial.width = style.lineWidth.evaluate(feature);
|
||||
}
|
||||
|
||||
polyline.setMaterial(polylineMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
for (const collection of this._collections.filter(isPolygonCollection)) {
|
||||
const featureTableId = this._collectionFeatureTableIds.get(collection);
|
||||
for (let i = 0, il = collection.primitiveCount; i < il; i++) {
|
||||
collection.get(i, polygon);
|
||||
const feature = this.getFeature(polygon.featureId, featureTableId);
|
||||
|
||||
if (defined(style.show)) {
|
||||
polygon.show = style.show.evaluate(feature);
|
||||
}
|
||||
if (defined(style.color)) {
|
||||
style.color.evaluate(feature, polygonMaterial.color);
|
||||
}
|
||||
|
||||
polygon.setMaterial(polygonMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Cesium3DTileset} _tileset
|
||||
* @param {FrameState} frameState
|
||||
*/
|
||||
update(_tileset, frameState) {
|
||||
const tileset = this._tileset;
|
||||
const vectorProvider = tileset._scene?.vectorProvider;
|
||||
|
||||
if (defined(this._model) && !this._ready) {
|
||||
const model = this._model;
|
||||
model.modelMatrix = this._tile.computedTransform;
|
||||
model.update(frameState);
|
||||
|
||||
// @ts-expect-error Requires Model conversion to ES6 class.
|
||||
if (model.ready) {
|
||||
initializeVectorPrimitives(this);
|
||||
this._ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
Matrix4.multiplyTransformation(
|
||||
this._tile.computedTransform,
|
||||
this._modelMatrix,
|
||||
scratchTileModelMatrix,
|
||||
);
|
||||
|
||||
// Only bake collections selected to render this frame (avoids duplicates).
|
||||
const isSelected =
|
||||
defined(vectorProvider) &&
|
||||
this._tile._selectedFrame === frameState.frameNumber;
|
||||
|
||||
for (let i = 0; i < this._collections.length; i++) {
|
||||
const collection = this._collections[i];
|
||||
Matrix4.multiplyTransformation(
|
||||
scratchTileModelMatrix,
|
||||
this._collectionLocalMatrices[i],
|
||||
collection.modelMatrix,
|
||||
);
|
||||
|
||||
if (!isHeightReferenceClamp(tileset._heightReference)) {
|
||||
collection.update(frameState);
|
||||
} else if (isSelected) {
|
||||
vectorProvider.markSelected(collection, frameState.frameNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Ray} _ray
|
||||
* @param {FrameState} _frameState
|
||||
* @param {Cartesian3|undefined} _result
|
||||
* @returns {Cartesian3|undefined}
|
||||
*/
|
||||
pick(_ray, _frameState, _result) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
isDestroyed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
const vectorProvider = this._tileset._scene?.vectorProvider;
|
||||
|
||||
this._model?.destroy();
|
||||
this._model = undefined;
|
||||
for (const collection of this._collections) {
|
||||
vectorProvider?.remove(collection);
|
||||
collection.destroy();
|
||||
}
|
||||
this._collections.length = 0;
|
||||
return destroyObject(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Cesium3DTileset} tileset
|
||||
* @param {Cesium3DTile} tile
|
||||
* @param {Resource} resource
|
||||
* @param {Uint8Array} glb GLB binary produced by buildVectorGltfFromMVT
|
||||
* @returns {Promise<VectorGltf3DTileContent>}
|
||||
*/
|
||||
static async fromGltf(tileset, tile, resource, glb) {
|
||||
const content = new VectorGltf3DTileContent(tileset, tile, resource);
|
||||
const modelOptions = makeModelOptions(tileset, tile, content, glb);
|
||||
const model = await Model.fromGltfAsync(modelOptions);
|
||||
// @ts-expect-error Requires Model conversion to ES6 class.
|
||||
model.show = false;
|
||||
content._model = model;
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Cesium3DTileset} tileset
|
||||
* @param {Cesium3DTile} tile
|
||||
* @param {VectorGltf3DTileContent} content
|
||||
* @param {Uint8Array} glb
|
||||
* @returns {*}
|
||||
* @ignore
|
||||
*/
|
||||
function makeModelOptions(tileset, tile, content, glb) {
|
||||
return {
|
||||
gltf: glb,
|
||||
basePath: content._resource,
|
||||
cull: false,
|
||||
releaseGltfJson: true,
|
||||
opaquePass: Pass.CESIUM_3D_TILE,
|
||||
modelMatrix: tile.computedTransform,
|
||||
upAxis: tileset._modelUpAxis,
|
||||
forwardAxis: tileset._modelForwardAxis,
|
||||
incrementallyLoadTextures: false,
|
||||
content: content,
|
||||
// @ts-expect-error Requires Cesium3DTileset conversion to ES6 class.
|
||||
featureIdLabel: tileset.featureIdLabel,
|
||||
// @ts-expect-error Requires Cesium3DTileset conversion to ES6 class.
|
||||
instanceFeatureIdLabel: tileset.instanceFeatureIdLabel,
|
||||
projectTo2D: tileset._projectTo2D,
|
||||
enablePick: tileset._enablePick,
|
||||
enableDebugWireframe: tileset._enableDebugWireframe,
|
||||
enableShowOutline: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {VectorGltf3DTileContent} content
|
||||
* @ignore
|
||||
*/
|
||||
function initializeVectorPrimitives(content) {
|
||||
// @ts-expect-error Requires Model conversion to ES6 class.
|
||||
const components = content._model.sceneGraph.components;
|
||||
|
||||
const axisCorrection = ModelUtility.getAxisCorrectionMatrix(
|
||||
components.upAxis,
|
||||
components.forwardAxis,
|
||||
new Matrix4(),
|
||||
);
|
||||
|
||||
Matrix4.multiplyTransformation(
|
||||
components.transform,
|
||||
axisCorrection,
|
||||
content._modelMatrix,
|
||||
);
|
||||
|
||||
const result = createVectorTileBuffersFromModelComponents(
|
||||
content,
|
||||
components,
|
||||
);
|
||||
|
||||
content._collections = result.collections;
|
||||
content._collectionLocalMatrices = result.collectionLocalMatrices;
|
||||
content._collectionFeatureTableIds = result.collectionFeatureTableIds;
|
||||
content._featuresByTableId = result.featuresByTableId;
|
||||
}
|
||||
|
||||
export default VectorGltf3DTileContent;
|
||||
Reference in New Issue
Block a user