Add existing to tracked
This commit is contained in:
+347
@@ -0,0 +1,347 @@
|
||||
// @ts-check
|
||||
|
||||
import assert from "../Core/assert.js";
|
||||
|
||||
/** @import BufferPrimitiveCollection from './BufferPrimitiveCollection.js'; */
|
||||
/** @import BufferPrimitiveMaterial from "./BufferPrimitiveMaterial.js"; */
|
||||
|
||||
/**
|
||||
* View bound to the underlying buffer data of a {@link BufferPrimitiveCollection}. Abstract.
|
||||
*
|
||||
* <p>BufferPrimitive instances are intended to be reused when iterating over large collections,
|
||||
* and temporarily bound to a primitive index while performing read/write operations on that primitive,
|
||||
* before being rebound to the next primitive, using the
|
||||
* {@link https://en.wikipedia.org/wiki/Flyweight_pattern|flyweight pattern}.</p>
|
||||
*
|
||||
* @see BufferPrimitiveCollection
|
||||
* @see BufferPrimitiveMaterial
|
||||
* @see BufferPoint
|
||||
* @see BufferPolyline
|
||||
* @see BufferPolygon
|
||||
*
|
||||
* @abstract
|
||||
* @experimental This feature is not final and is subject to change without Cesium's standard deprecation policy.
|
||||
*/
|
||||
class BufferPrimitive {
|
||||
/**
|
||||
* Collecton containing the primitive(s) for which this instance currently
|
||||
* provides a view.
|
||||
*
|
||||
* @type {BufferPrimitiveCollection<BufferPrimitive>}
|
||||
* @ignore
|
||||
*/
|
||||
_collection = null;
|
||||
|
||||
/**
|
||||
* Index of the primitive for which this instance currently provides a view.
|
||||
*
|
||||
* @type {number}
|
||||
* @ignore
|
||||
*/
|
||||
_index = -1;
|
||||
|
||||
/**
|
||||
* Byte offset, into the collection's primitive buffer, of the primitive for
|
||||
* which this instance currently provides a view.
|
||||
*
|
||||
* @type {number}
|
||||
* @ignore
|
||||
*/
|
||||
_byteOffset = -1;
|
||||
|
||||
/**
|
||||
* Binary layout for this primitive type in collection's primitive buffer.
|
||||
* Each `Layout.MY_KEY_U32` entry is an offset in bytes, relative to the
|
||||
* start offset of the primitive, with the suffix indicating the data type
|
||||
* stored at that offset.
|
||||
*
|
||||
* The final entry, `__BYTE_LENGTH`, is not a pointer into a buffer — its
|
||||
* literal value is the total byte length of one primitive in the primitive
|
||||
* buffer, exclusive of other buffers.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
static Layout = {
|
||||
/**
|
||||
* Feature ID associated with the primitive; not required to be unique.
|
||||
* @type {number}
|
||||
* @ignore
|
||||
*/
|
||||
FEATURE_ID_U32: 0,
|
||||
|
||||
/**
|
||||
* Boolean (0 or 1) flag indicating whether primitive is shown.
|
||||
* @type {number}
|
||||
* @ignore
|
||||
*/
|
||||
SHOW_U8: 4,
|
||||
|
||||
/**
|
||||
* Boolean (0 or 1) flag indicating whether primitive is dirty.
|
||||
* @type {number}
|
||||
* @ignore
|
||||
*/
|
||||
DIRTY_U8: 5,
|
||||
|
||||
/**
|
||||
* Pick ID (uint32) of primitive.
|
||||
* @type {number}
|
||||
* @ignore
|
||||
*/
|
||||
PICK_ID_U32: 8,
|
||||
|
||||
/**
|
||||
* Byte length of one primitive in the primitive buffer, exclusive of
|
||||
* other buffers. Literal value, not a pointer.
|
||||
* @type {number}
|
||||
* @ignore
|
||||
*/
|
||||
__BYTE_LENGTH: 12,
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// LIFECYCLE
|
||||
|
||||
/**
|
||||
* Copies data from source primitive to result. If the result primitive is not
|
||||
* new (the last primitive in the collection) then source and result primitives
|
||||
* must have the same vertex counts.
|
||||
*
|
||||
* @param {BufferPrimitive} primitive
|
||||
* @param {BufferPrimitive} result
|
||||
* @returns {BufferPrimitive}
|
||||
*/
|
||||
static clone(primitive, result) {
|
||||
const SrcMaterialClass = primitive._collection._getMaterialClass();
|
||||
|
||||
//>>includeStart('debug', pragmas.debug);
|
||||
const DstMaterialClass = result._collection._getMaterialClass();
|
||||
assert(SrcMaterialClass === DstMaterialClass, "Incompatible materials");
|
||||
//>>includeEnd('debug');
|
||||
|
||||
result.featureId = primitive.featureId;
|
||||
result.show = primitive.show;
|
||||
result.setMaterial(primitive.getMaterial(new SrcMaterialClass()));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this primitive's memory footprint is resizable. Only the
|
||||
* newest (most recently created) primitive in a collection can be resized,
|
||||
* to guarantee fast and stable performance.
|
||||
*
|
||||
* @returns {boolean}
|
||||
* @protected
|
||||
* @ignore
|
||||
*/
|
||||
_isResizable() {
|
||||
return this._index === this._collection.primitiveCount - 1;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// ACCESSORS
|
||||
|
||||
/**
|
||||
* Feature ID associated with the primitive; not required to be unique.
|
||||
* @type {number}
|
||||
*/
|
||||
get featureId() {
|
||||
return this._getUint32(BufferPrimitive.Layout.FEATURE_ID_U32);
|
||||
}
|
||||
|
||||
set featureId(featureId) {
|
||||
this._setUint32(BufferPrimitive.Layout.FEATURE_ID_U32, featureId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether primitive is shown.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get show() {
|
||||
return this._getUint8(BufferPrimitive.Layout.SHOW_U8) === 1;
|
||||
}
|
||||
|
||||
set show(show) {
|
||||
this._setUint8(BufferPrimitive.Layout.SHOW_U8, show ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BufferPrimitiveMaterial} result
|
||||
* @returns {BufferPrimitiveMaterial}
|
||||
*/
|
||||
getMaterial(result) {
|
||||
const collection = this._collection;
|
||||
const MaterialClass = collection._getMaterialClass();
|
||||
|
||||
return MaterialClass.unpack(
|
||||
collection._materialView,
|
||||
this._index * MaterialClass.packedLength,
|
||||
result,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BufferPrimitiveMaterial} material
|
||||
*/
|
||||
setMaterial(material) {
|
||||
const collection = this._collection;
|
||||
const MaterialClass = collection._getMaterialClass();
|
||||
|
||||
MaterialClass.pack(
|
||||
material,
|
||||
collection._materialView,
|
||||
this._index * MaterialClass.packedLength,
|
||||
);
|
||||
|
||||
this._dirty = true;
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the primitive requires an update on next render. Renderers should
|
||||
* _not_ iterate over all primitives each frame, but must instead inspect
|
||||
* only the dirty range of the parent collection. This flag is managed
|
||||
* automatically, by primitive setters and collection renderers.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @ignore
|
||||
*
|
||||
* @see BufferPrimitiveCollection#_dirtyOffset
|
||||
* @see BufferPrimitiveCollection#_dirtyCount
|
||||
*/
|
||||
get _dirty() {
|
||||
return this._getUint8(BufferPrimitive.Layout.DIRTY_U8) === 1;
|
||||
}
|
||||
|
||||
set _dirty(dirty) {
|
||||
// Avoid `._setUint8()` here, which would infinitely loop `._dirty = true`.
|
||||
this._collection._primitiveView.setUint8(
|
||||
this._byteOffset + BufferPrimitive.Layout.DIRTY_U8,
|
||||
dirty ? 1 : 0,
|
||||
);
|
||||
|
||||
// A 'dirty' primitive is responsible for notifying the collection. Applying
|
||||
// updates and marking the primitive 'clean' will be handled by the collection,
|
||||
// so we don't notify the collection here in that case.
|
||||
if (dirty) {
|
||||
this._collection._makeDirty(this._index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick ID (uint32) of primitive.
|
||||
* @type {number}
|
||||
* @ignore
|
||||
*/
|
||||
get _pickId() {
|
||||
return this._getUint32(BufferPrimitive.Layout.PICK_ID_U32);
|
||||
}
|
||||
|
||||
set _pickId(pickId) {
|
||||
this._setUint32(BufferPrimitive.Layout.PICK_ID_U32, pickId);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// BUFFER ACCESSORS
|
||||
|
||||
/**
|
||||
* @param {number} itemByteOffset
|
||||
* @returns {number}
|
||||
* @ignore
|
||||
*/
|
||||
_getUint8(itemByteOffset) {
|
||||
return this._collection._primitiveView.getUint8(
|
||||
this._byteOffset + itemByteOffset,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} itemByteOffset
|
||||
* @param {number} itemValue
|
||||
* @ignore
|
||||
*/
|
||||
_setUint8(itemByteOffset, itemValue) {
|
||||
this._collection._primitiveView.setUint8(
|
||||
this._byteOffset + itemByteOffset,
|
||||
itemValue,
|
||||
);
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} itemByteOffset
|
||||
* @returns {number}
|
||||
* @ignore
|
||||
*/
|
||||
_getUint32(itemByteOffset) {
|
||||
return this._collection._primitiveView.getUint32(
|
||||
this._byteOffset + itemByteOffset,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} itemByteOffset
|
||||
* @param {number} itemValue
|
||||
* @ignore
|
||||
*/
|
||||
_setUint32(itemByteOffset, itemValue) {
|
||||
this._collection._primitiveView.setUint32(
|
||||
this._byteOffset + itemByteOffset,
|
||||
itemValue,
|
||||
true,
|
||||
);
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} itemByteOffset
|
||||
* @returns {number}
|
||||
* @ignore
|
||||
*/
|
||||
_getFloat32(itemByteOffset) {
|
||||
return this._collection._primitiveView.getFloat32(
|
||||
this._byteOffset + itemByteOffset,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} itemByteOffset
|
||||
* @param {number} itemValue
|
||||
* @ignore
|
||||
*/
|
||||
_setFloat32(itemByteOffset, itemValue) {
|
||||
this._collection._primitiveView.setFloat32(
|
||||
this._byteOffset + itemByteOffset,
|
||||
itemValue,
|
||||
true,
|
||||
);
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// DEBUG
|
||||
|
||||
/**
|
||||
* Returns a JSON-serializable object representing the primitive. This encoding
|
||||
* is not memory-efficient, and should generally be used for debugging and
|
||||
* testing.
|
||||
*
|
||||
* @returns {Object} JSON-serializable object.
|
||||
*/
|
||||
toJSON() {
|
||||
const collection = this._collection;
|
||||
const MaterialClass = collection._getMaterialClass();
|
||||
|
||||
return {
|
||||
featureId: this.featureId,
|
||||
show: this.show,
|
||||
dirty: this._dirty,
|
||||
material: this.getMaterial(new MaterialClass()).toJSON(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default BufferPrimitive;
|
||||
Reference in New Issue
Block a user