Add existing to tracked
This commit is contained in:
+380
@@ -0,0 +1,380 @@
|
||||
// @ts-check
|
||||
|
||||
import defined from "../Core/defined.js";
|
||||
import BufferPrimitiveCollection from "./BufferPrimitiveCollection.js";
|
||||
import BufferPolygon from "./BufferPolygon.js";
|
||||
import Frozen from "../Core/Frozen.js";
|
||||
import assert from "../Core/assert.js";
|
||||
import IndexDatatype from "../Core/IndexDatatype.js";
|
||||
import renderPolygons from "./renderBufferPolygonCollection.js";
|
||||
import BufferPolygonMaterial from "./BufferPolygonMaterial.js";
|
||||
|
||||
/** @import BlendOption from "./BlendOption.js"; */
|
||||
/** @import BoundingSphere from "../Core/BoundingSphere.js"; */
|
||||
/** @import { TypedArray } from "../Core/globalTypes.js"; */
|
||||
/** @import Matrix4 from "../Core/Matrix4.js"; */
|
||||
/** @import FrameState from "./FrameState.js" */
|
||||
/** @import ComponentDatatype from "../Core/ComponentDatatype.js"; */
|
||||
|
||||
const { ERR_CAPACITY } = BufferPrimitiveCollection.Error;
|
||||
|
||||
/**
|
||||
* @typedef {object} BufferPolygonOptions
|
||||
* @property {Matrix4} [modelMatrix=Matrix4.IDENTITY] Transforms geometry from model to world coordinates.
|
||||
* @property {boolean} [show=true]
|
||||
* @property {BufferPolygonMaterial} [material=BufferPolygonMaterial.DEFAULT_MATERIAL]
|
||||
* @property {number} [featureId]
|
||||
* @property {object} [pickObject]
|
||||
* @property {TypedArray} [positions]
|
||||
* @property {TypedArray} [holes]
|
||||
* @property {TypedArray} [triangles]
|
||||
* @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Collection of polygons held in ArrayBuffer storage for performance and memory optimization.
|
||||
*
|
||||
* <p>Default buffer memory allocation is arbitrary, and collections cannot be resized,
|
||||
* so specific per-buffer capacities should be provided in the collection
|
||||
* constructor when available.</p>
|
||||
*
|
||||
* @example
|
||||
* import earcut from "earcut";
|
||||
*
|
||||
* const collection = new BufferPolygonCollection({
|
||||
* primitiveCountMax: 1024,
|
||||
* vertexCountMax: 4096,
|
||||
* holeCountMax: 1024,
|
||||
* triangleCountMax: 2048,
|
||||
* });
|
||||
*
|
||||
* const polygon = new BufferPolygon();
|
||||
* const positions = [ ... ];
|
||||
* const holes = [ ... ];
|
||||
* const material = new BufferPolygonMaterial({color: Color.WHITE});
|
||||
*
|
||||
* // Create a new polygon, temporarily bound to 'polygon' local variable.
|
||||
* collection.add({
|
||||
* positions: new Float64Array(positions),
|
||||
* holes: new Uint32Array(holes),
|
||||
* triangles: new Uint32Array(earcut(positions, holes, 3)),
|
||||
* material
|
||||
* }, polygon);
|
||||
*
|
||||
* // Iterate over all polygons in collection, temporarily binding 'polygon'
|
||||
* // local variable to each, and updating polygon material.
|
||||
* for (let i = 0; i < collection.primitiveCount; i++) {
|
||||
* collection.get(i, polygon);
|
||||
* polygon.setMaterial(material);
|
||||
* }
|
||||
*
|
||||
* @see BufferPolygon
|
||||
* @see BufferPolygonMaterial
|
||||
* @see BufferPrimitiveCollection
|
||||
* @extends BufferPrimitiveCollection<BufferPolygon>
|
||||
* @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
|
||||
*/
|
||||
class BufferPolygonCollection extends BufferPrimitiveCollection {
|
||||
/**
|
||||
* @param {object} options
|
||||
* @param {number} [options.primitiveCountMax=BufferPrimitiveCollection.DEFAULT_CAPACITY]
|
||||
* @param {number} [options.vertexCountMax=BufferPrimitiveCollection.DEFAULT_CAPACITY]
|
||||
* @param {number} [options.holeCountMax=BufferPrimitiveCollection.DEFAULT_CAPACITY]
|
||||
* @param {number} [options.triangleCountMax=BufferPrimitiveCollection.DEFAULT_CAPACITY]
|
||||
* @param {ComponentDatatype} [options.positionDatatype=ComponentDatatype.DOUBLE]
|
||||
* @param {boolean} [options.positionNormalized=false]
|
||||
* @param {boolean} [options.show=true]
|
||||
* @param {boolean} [options.allowPicking=true] When <code>true</code>, primitives are pickable with {@link Scene#pick}. When <code>false</code>, memory and initialization cost are lower.
|
||||
* @param {BoundingSphere} [options.boundingVolume] Bounding volume, in world space, for the collection. When
|
||||
* unspecified, a bounding volume is computed automatically and updated when primitive positions change. When
|
||||
* specified, users are responsible for updating bounding volume as needed. Pre-computing the bounding volume
|
||||
* manually, and updating it only as needed, will improve performance for larger dynamic collections.
|
||||
* @param {boolean} [options.debugShowBoundingVolume=false]
|
||||
* @param {BlendOption} [options.blendOption=BlendOption.TRANSLUCENT]
|
||||
*/
|
||||
constructor(options = Frozen.EMPTY_OBJECT) {
|
||||
super(options);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @ignore
|
||||
*/
|
||||
this._holeCount = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @protected
|
||||
* @ignore
|
||||
*/
|
||||
this._holeCountMax =
|
||||
options.holeCountMax ?? BufferPrimitiveCollection.DEFAULT_CAPACITY;
|
||||
|
||||
/**
|
||||
* @type {TypedArray}
|
||||
* @ignore
|
||||
*/
|
||||
this._holeIndexView = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @ignore
|
||||
*/
|
||||
this._triangleCount = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @protected
|
||||
* @ignore
|
||||
*/
|
||||
this._triangleCountMax =
|
||||
options.triangleCountMax ?? BufferPrimitiveCollection.DEFAULT_CAPACITY;
|
||||
|
||||
/**
|
||||
* @type {TypedArray}
|
||||
* @ignore
|
||||
*/
|
||||
this._triangleIndexView = null;
|
||||
|
||||
this._allocateHoleIndexBuffer();
|
||||
this._allocateTriangleIndexBuffer();
|
||||
}
|
||||
|
||||
_getCollectionClass() {
|
||||
return BufferPolygonCollection;
|
||||
}
|
||||
|
||||
_getPrimitiveClass() {
|
||||
return BufferPolygon;
|
||||
}
|
||||
|
||||
_getMaterialClass() {
|
||||
return BufferPolygonMaterial;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// COLLECTION LIFECYCLE
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @ignore
|
||||
*/
|
||||
_allocateHoleIndexBuffer() {
|
||||
// @ts-expect-error Requires https://github.com/CesiumGS/cesium/pull/13203.
|
||||
this._holeIndexView = IndexDatatype.createTypedArray(
|
||||
this._positionCountMax,
|
||||
this._holeCountMax,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @ignore
|
||||
*/
|
||||
_allocateTriangleIndexBuffer() {
|
||||
// @ts-expect-error Requires https://github.com/CesiumGS/cesium/pull/13203.
|
||||
this._triangleIndexView = IndexDatatype.createTypedArray(
|
||||
this._positionCountMax,
|
||||
this._triangleCountMax * 3,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates the contents of this collection into the result collection.
|
||||
* Result collection is not resized, and must contain enough space for all
|
||||
* primitives in the source collection. Existing polygons in the result
|
||||
* collection will be overwritten.
|
||||
*
|
||||
* <p>Useful when allocating more space for a collection that has reached its
|
||||
* capacity, and efficiently transferring polygons to the new collection.</p>
|
||||
*
|
||||
* @example
|
||||
* const result = new BufferPolygonCollection({ ... }); // allocate larger 'result' collection
|
||||
* BufferPolygonCollection.clone(collection, result); // copy polygons from 'collection' into 'result'
|
||||
*
|
||||
* @param {BufferPolygonCollection} collection
|
||||
* @param {BufferPolygonCollection} result
|
||||
* @returns {BufferPolygonCollection}
|
||||
*/
|
||||
static clone(collection, result) {
|
||||
super.clone(collection, result);
|
||||
|
||||
//>>includeStart('debug', pragmas.debug);
|
||||
assert(collection.holeCount <= result.holeCountMax, ERR_CAPACITY);
|
||||
assert(collection.triangleCount <= result.triangleCountMax, ERR_CAPACITY);
|
||||
//>>includeEnd('debug');
|
||||
|
||||
this._copySubArray(
|
||||
collection._holeIndexView,
|
||||
result._holeIndexView,
|
||||
collection.holeCount,
|
||||
);
|
||||
|
||||
this._copySubArray(
|
||||
collection._triangleIndexView,
|
||||
result._triangleIndexView,
|
||||
collection._triangleCount * 3,
|
||||
);
|
||||
|
||||
result._holeCount = collection._holeCount;
|
||||
result._triangleCount = collection._triangleCount;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BufferPolygonCollection} collection
|
||||
* @returns {BufferPolygonCollection}
|
||||
* @override
|
||||
* @ignore
|
||||
*/
|
||||
static _cloneEmpty(collection) {
|
||||
return new BufferPolygonCollection({
|
||||
primitiveCountMax: collection.primitiveCountMax,
|
||||
vertexCountMax: collection.vertexCountMax,
|
||||
holeCountMax: collection.holeCountMax,
|
||||
triangleCountMax: collection.triangleCountMax,
|
||||
positionDatatype: collection.positionDatatype,
|
||||
positionNormalized: collection.positionNormalized,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BufferPolygonCollection} src
|
||||
* @param {BufferPolygonCollection} dst
|
||||
* @override
|
||||
* @ignore
|
||||
*/
|
||||
static _replaceBuffers(src, dst) {
|
||||
super._replaceBuffers(src, dst);
|
||||
dst._holeIndexView = src._holeIndexView;
|
||||
dst._triangleIndexView = src._triangleIndexView;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// PRIMITIVE LIFECYCLE
|
||||
|
||||
/**
|
||||
* Adds a new polygon to the collection, with the specified options. A
|
||||
* {@link BufferPolygon} instance is linked to the new polygon, using
|
||||
* the 'result' argument if given, or a new instance if not. For repeated
|
||||
* calls, prefer to reuse a single BufferPolygon instance rather than
|
||||
* allocating a new instance on each call.
|
||||
*
|
||||
* @param {BufferPolygonOptions} options
|
||||
* @param {BufferPolygon} result
|
||||
* @returns {BufferPolygon}
|
||||
* @override
|
||||
*/
|
||||
add(options, result = new BufferPolygon()) {
|
||||
super.add(options, result);
|
||||
|
||||
const vertexOffset = this._positionCount;
|
||||
result._setUint32(BufferPolygon.Layout.POSITION_OFFSET_U32, vertexOffset);
|
||||
result._setUint32(BufferPolygon.Layout.POSITION_COUNT_U32, 0);
|
||||
|
||||
const holeOffset = this._holeCount;
|
||||
result._setUint32(BufferPolygon.Layout.HOLE_OFFSET_U32, holeOffset);
|
||||
result._setUint32(BufferPolygon.Layout.HOLE_COUNT_U32, 0);
|
||||
|
||||
const triangleOffset = this._triangleCount;
|
||||
result._setUint32(BufferPolygon.Layout.TRIANGLE_OFFSET_U32, triangleOffset);
|
||||
result._setUint32(BufferPolygon.Layout.TRIANGLE_COUNT_U32, 0);
|
||||
|
||||
if (defined(options.positions)) {
|
||||
result.setPositions(options.positions);
|
||||
}
|
||||
|
||||
if (defined(options.holes)) {
|
||||
result.setHoles(options.holes);
|
||||
}
|
||||
|
||||
if (defined(options.triangles)) {
|
||||
result.setTriangles(options.triangles);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// RENDER
|
||||
|
||||
/**
|
||||
* @param {FrameState} frameState
|
||||
* @ignore
|
||||
*/
|
||||
update(frameState) {
|
||||
super.update(frameState);
|
||||
|
||||
const passes = frameState.passes;
|
||||
if (this.show && (passes.render || passes.pick)) {
|
||||
this._renderContext = renderPolygons(
|
||||
this,
|
||||
frameState,
|
||||
this._renderContext,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// ACCESSORS
|
||||
|
||||
/**
|
||||
* Total byte length of buffers owned by this collection. Includes any unused
|
||||
* space allocated by {@link primitiveCountMax}, even if no polygons have
|
||||
* yet been added in that space.
|
||||
*
|
||||
* @type {number}
|
||||
* @readonly
|
||||
* @override
|
||||
*/
|
||||
get byteLength() {
|
||||
return (
|
||||
super.byteLength +
|
||||
this._holeIndexView.byteLength +
|
||||
this._triangleIndexView.byteLength
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of holes in collection. Must be <= {@link holeCountMax}.
|
||||
*
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get holeCount() {
|
||||
return this._holeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum number of holes in collection. Must be >= {@link holeCount}.
|
||||
*
|
||||
* @type {number}
|
||||
* @readonly
|
||||
* @default {@link BufferPrimitiveCollection.DEFAULT_CAPACITY}
|
||||
*/
|
||||
get holeCountMax() {
|
||||
return this._holeCountMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of triangles in collection. Must be <= {@link triangleCountMax}.
|
||||
*
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get triangleCount() {
|
||||
return this._triangleCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum number of triangles in collection. Must be >= {@link triangleCount}.
|
||||
*
|
||||
* @type {number}
|
||||
* @readonly
|
||||
* @default {@link BufferPrimitiveCollection.DEFAULT_CAPACITY}
|
||||
*/
|
||||
get triangleCountMax() {
|
||||
return this._triangleCountMax;
|
||||
}
|
||||
}
|
||||
export default BufferPolygonCollection;
|
||||
Reference in New Issue
Block a user