UNPKG

@itwin/core-frontend

Version:
110 lines 4.81 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module WebGL */ import { assert, Id64, lowerBound } from "@itwin/core-bentley"; /** * Assigns a transient, unique 32-bit integer ID to each Batch in a RenderCommands. * A batch ID of 0 means "no batch". * The first batch gets batch ID of 1. * The next batch gets the previous batch's ID plus the number of features in the previous batch's feature table * (or 1, if empty feature table). * The IDs are set temporarily as members on the Batch objects and reset to 0 immediately after rendering. * The currentBatch member identifies the batch containing primitives currently being drawn. * The combination of the current batch's ID (passed as uniform to shader) and the index of a given Feature within * its batch's FeatureTable (stored in vertex table) produce a unique ID for every feature rendered during a frame. * During rendering, the feature IDs are written to the "feature ID" color attachment. * The batch IDs remain valid during a call to Target.readPixels() so that they can be used to extract * Features from the Batch's FeatureTables. * @internal */ export class BatchState { _stack; _batches = []; // NB: this list is ordered - but *not* indexed - by batch ID. _curBatch; constructor(stack) { this._stack = stack; } get currentBatch() { return this._curBatch; } get currentBatchId() { return undefined !== this._curBatch ? this._curBatch.batchId : 0; } get currentBatchIModel() { return undefined !== this._curBatch ? this._curBatch.batchIModel : undefined; } get isEmpty() { return 0 === this._batches.length; } push(batch, allowAdd) { assert(undefined === this.currentBatch, "batches cannot nest"); this.getBatchId(batch, allowAdd); this._curBatch = batch; } pop() { assert(undefined !== this.currentBatch); this._curBatch = undefined; } reset() { assert(undefined === this.currentBatch); for (const batch of this._batches) batch.resetContext(); this._batches.length = 0; this._curBatch = undefined; } static _scratchElementIdPair = { lower: 0, upper: 0 }; getElementId(featureId) { const batch = this.find(featureId); if (undefined === batch) return Id64.invalid; const featureIndex = featureId - batch.batchId; assert(featureIndex >= 0); const parts = batch.featureTable.getElementIdPair(featureIndex, BatchState._scratchElementIdPair); return Id64.fromUint32Pair(parts.lower, parts.upper); } getFeature(featureId, result) { const batch = this.find(featureId); if (undefined === batch) return undefined; const featureIndex = featureId - batch.batchId; assert(featureIndex >= 0); return batch.featureTable.findFeature(featureIndex, result); } get numFeatureIds() { return this.nextBatchId; } get numBatches() { return this._batches.length; } findBatchId(featureId) { const batch = this.find(featureId); return undefined !== batch ? batch.batchId : 0; } get nextBatchId() { if (this.isEmpty) return 1; const prev = this._batches[this._batches.length - 1]; assert(0 !== prev.batchId); let prevNumFeatures = prev.featureTable.numFeatures; if (0 === prevNumFeatures) prevNumFeatures = 1; return prev.batchId + prevNumFeatures; } getBatchId(batch, allowAdd) { if (allowAdd && 0 === batch.batchId) { batch.setContext(this.nextBatchId, this._stack.top); this._batches.push(batch); } return batch.batchId; } indexOf(featureId) { if (featureId <= 0) return -1; const found = lowerBound(featureId, this._batches, (lhs, rhs) => { // Determine if the requested feature ID is within the range of this batch. if (lhs < rhs.batchId) return -1; const numFeatures = rhs.featureTable.numFeatures; const nextBatchId = rhs.batchId + (numFeatures > 0 ? numFeatures : 1); return lhs < nextBatchId ? 0 : 1; }); return found.index < this._batches.length ? found.index : -1; } find(featureId) { const index = this.indexOf(featureId); return -1 !== index ? this._batches[index] : undefined; } } //# sourceMappingURL=BatchState.js.map