1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210 |
- import Cartesian3 from '../Core/Cartesian3.js';
- import Color from '../Core/Color.js';
- import ComponentDatatype from '../Core/ComponentDatatype.js';
- import defaultValue from '../Core/defaultValue.js';
- import defined from '../Core/defined.js';
- import defineProperties from '../Core/defineProperties.js';
- import destroyObject from '../Core/destroyObject.js';
- import IndexDatatype from '../Core/IndexDatatype.js';
- import Matrix4 from '../Core/Matrix4.js';
- import PrimitiveType from '../Core/PrimitiveType.js';
- import Buffer from '../Renderer/Buffer.js';
- import BufferUsage from '../Renderer/BufferUsage.js';
- import DrawCommand from '../Renderer/DrawCommand.js';
- import Pass from '../Renderer/Pass.js';
- import RenderState from '../Renderer/RenderState.js';
- import ShaderProgram from '../Renderer/ShaderProgram.js';
- import ShaderSource from '../Renderer/ShaderSource.js';
- import VertexArray from '../Renderer/VertexArray.js';
- import ShadowVolumeFS from '../Shaders/ShadowVolumeFS.js';
- import VectorTileVS from '../Shaders/VectorTileVS.js';
- import BlendingState from './BlendingState.js';
- import Cesium3DTileFeature from './Cesium3DTileFeature.js';
- import ClassificationType from './ClassificationType.js';
- import DepthFunction from './DepthFunction.js';
- import Expression from './Expression.js';
- import StencilConstants from './StencilConstants.js';
- import StencilFunction from './StencilFunction.js';
- import StencilOperation from './StencilOperation.js';
- import Vector3DTileBatch from './Vector3DTileBatch.js';
- /**
- * Creates a batch of classification meshes.
- *
- * @alias Vector3DTilePrimitive
- * @constructor
- *
- * @param {Object} options An object with following properties:
- * @param {Float32Array} options.positions The positions of the meshes.
- * @param {Uint16Array|Uint32Array} options.indices The indices of the triangulated meshes. The indices must be contiguous so that
- * the indices for mesh n are in [i, i + indexCounts[n]] where i = sum{indexCounts[0], indexCounts[n - 1]}.
- * @param {Uint32Array} options.indexCounts The number of indices for each mesh.
- * @param {Uint32Array} options.indexOffsets The offset into the index buffer for each mesh.
- * @param {Vector3DTileBatch[]} options.batchedIndices The index offset and count for each batch with the same color.
- * @param {Cartesian3} [options.center=Cartesian3.ZERO] The RTC center.
- * @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched meshes.
- * @param {Uint16Array} options.batchIds The batch ids for each mesh.
- * @param {Uint16Array} options.vertexBatchIds The batch id for each vertex.
- * @param {BoundingSphere} options.boundingVolume The bounding volume for the entire batch of meshes.
- * @param {BoundingSphere[]} options.boundingVolumes The bounding volume for each mesh.
- * @param {ClassificationType} [options.classificationType] What this tile will classify.
- *
- * @private
- */
- function Vector3DTilePrimitive(options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- this._batchTable = options.batchTable;
- this._batchIds = options.batchIds;
- // These arrays are released after VAO creation.
- this._positions = options.positions;
- this._vertexBatchIds = options.vertexBatchIds;
- // These arrays are kept for re-batching indices based on colors.
- // If WebGL 2 is supported, indices will be released and re-batching uses buffer-to-buffer copies.
- this._indices = options.indices;
- this._indexCounts = options.indexCounts;
- this._indexOffsets = options.indexOffsets;
- this._batchedIndices = options.batchedIndices;
- this._boundingVolume = options.boundingVolume;
- this._boundingVolumes = options.boundingVolumes;
- this._center = defaultValue(options.center, Cartesian3.ZERO);
- this._va = undefined;
- this._sp = undefined;
- this._spStencil = undefined;
- this._spPick = undefined;
- this._uniformMap = undefined;
- // Only used with WebGL 2 to ping-pong ibos after copy.
- this._vaSwap = undefined;
- this._rsStencilPreloadPass = undefined;
- this._rsStencilPreloadPass3DTiles = undefined;
- this._rsStencilDepthPass = undefined;
- this._rsStencilDepthPass3DTiles = undefined;
- this._rsColorPass = undefined;
- this._rsPickPass = undefined;
- this._rsWireframe = undefined;
- this._commands = [];
- this._commandsIgnoreShow = [];
- this._pickCommands = [];
- this._constantColor = Color.clone(Color.WHITE);
- this._highlightColor = this._constantColor;
- this._batchDirty = true;
- this._pickCommandsDirty = true;
- this._framesSinceLastRebatch = 0;
- this._updatingAllCommands = false;
- this._trianglesLength = this._indices.length / 3;
- this._geometryByteLength = this._indices.byteLength + this._positions.byteLength + this._vertexBatchIds.byteLength;
- /**
- * Draw the wireframe of the classification meshes.
- * @type {Boolean}
- * @default false
- */
- this.debugWireframe = false;
- this._debugWireframe = this.debugWireframe;
- this._wireframeDirty = false;
- /**
- * Forces a re-batch instead of waiting after a number of frames have been rendered. For testing only.
- * @type {Boolean}
- * @default false
- */
- this.forceRebatch = false;
- /**
- * What this tile will classify.
- * @type {ClassificationType}
- * @default ClassificationType.BOTH
- */
- this.classificationType = defaultValue(options.classificationType, ClassificationType.BOTH);
- // Hidden options
- this._vertexShaderSource = options._vertexShaderSource;
- this._fragmentShaderSource = options._fragmentShaderSource;
- this._attributeLocations = options._attributeLocations;
- this._uniformMap = options._uniformMap;
- this._pickId = options._pickId;
- this._modelMatrix = options._modelMatrix;
- this._boundingSphere = options._boundingSphere;
- this._batchIdLookUp = {};
- var length = this._batchIds.length;
- for (var i = 0; i < length; ++i) {
- var batchId = this._batchIds[i];
- this._batchIdLookUp[batchId] = i;
- }
- }
- defineProperties(Vector3DTilePrimitive.prototype, {
- /**
- * Gets the number of triangles.
- *
- * @memberof Vector3DTilePrimitive.prototype
- *
- * @type {Number}
- * @readonly
- */
- trianglesLength : {
- get : function() {
- return this._trianglesLength;
- }
- },
- /**
- * Gets the geometry memory in bytes.
- *
- * @memberof Vector3DTilePrimitive.prototype
- *
- * @type {Number}
- * @readonly
- */
- geometryByteLength : {
- get : function() {
- return this._geometryByteLength;
- }
- }
- });
- var defaultAttributeLocations = {
- position : 0,
- a_batchId : 1
- };
- function createVertexArray(primitive, context) {
- if (defined(primitive._va)) {
- return;
- }
- var positionBuffer = Buffer.createVertexBuffer({
- context : context,
- typedArray : primitive._positions,
- usage : BufferUsage.STATIC_DRAW
- });
- var idBuffer = Buffer.createVertexBuffer({
- context : context,
- typedArray : primitive._vertexBatchIds,
- usage : BufferUsage.STATIC_DRAW
- });
- var indexBuffer = Buffer.createIndexBuffer({
- context : context,
- typedArray : primitive._indices,
- usage : BufferUsage.DYNAMIC_DRAW,
- indexDatatype : (primitive._indices.BYTES_PER_ELEMENT === 2) ? IndexDatatype.UNSIGNED_SHORT : IndexDatatype.UNSIGNED_INT
- });
- var vertexAttributes = [{
- index : 0,
- vertexBuffer : positionBuffer,
- componentDatatype : ComponentDatatype.fromTypedArray(primitive._positions),
- componentsPerAttribute : 3
- }, {
- index : 1,
- vertexBuffer : idBuffer,
- componentDatatype : ComponentDatatype.fromTypedArray(primitive._vertexBatchIds),
- componentsPerAttribute : 1
- }];
- primitive._va = new VertexArray({
- context : context,
- attributes : vertexAttributes,
- indexBuffer : indexBuffer
- });
- if (context.webgl2) {
- primitive._vaSwap = new VertexArray({
- context : context,
- attributes : vertexAttributes,
- indexBuffer : Buffer.createIndexBuffer({
- context : context,
- sizeInBytes : indexBuffer.sizeInBytes,
- usage : BufferUsage.DYNAMIC_DRAW,
- indexDatatype : indexBuffer.indexDatatype
- })
- });
- }
- primitive._batchedPositions = undefined;
- primitive._transferrableBatchIds = undefined;
- primitive._vertexBatchIds = undefined;
- primitive._verticesPromise = undefined;
- }
- function createShaders(primitive, context) {
- if (defined(primitive._sp)) {
- return;
- }
- var batchTable = primitive._batchTable;
- var attributeLocations = defaultValue(primitive._attributeLocations, defaultAttributeLocations);
- var pickId = primitive._pickId;
- var vertexShaderSource = primitive._vertexShaderSource;
- var fragmentShaderSource = primitive._fragmentShaderSource;
- if (defined(vertexShaderSource)) {
- primitive._sp = ShaderProgram.fromCache({
- context : context,
- vertexShaderSource : vertexShaderSource,
- fragmentShaderSource : fragmentShaderSource,
- attributeLocations : attributeLocations
- });
- primitive._spStencil = primitive._sp;
- fragmentShaderSource = ShaderSource.replaceMain(fragmentShaderSource, 'czm_non_pick_main');
- fragmentShaderSource =
- fragmentShaderSource +
- 'void main() \n' +
- '{ \n' +
- ' czm_non_pick_main(); \n' +
- ' gl_FragColor = ' + pickId + '; \n' +
- '} \n';
- primitive._spPick = ShaderProgram.fromCache({
- context : context,
- vertexShaderSource : vertexShaderSource,
- fragmentShaderSource : fragmentShaderSource,
- attributeLocations : attributeLocations
- });
- return;
- }
- var vsSource = batchTable.getVertexShaderCallback(false, 'a_batchId', undefined)(VectorTileVS);
- var fsSource = batchTable.getFragmentShaderCallback()(ShadowVolumeFS, false, undefined);
- pickId = batchTable.getPickId();
- var vs = new ShaderSource({
- sources : [vsSource]
- });
- var fs = new ShaderSource({
- defines : ['VECTOR_TILE'],
- sources : [fsSource]
- });
- primitive._sp = ShaderProgram.fromCache({
- context : context,
- vertexShaderSource : vs,
- fragmentShaderSource : fs,
- attributeLocations : attributeLocations
- });
- vs = new ShaderSource({
- sources : [VectorTileVS]
- });
- fs = new ShaderSource({
- defines : ['VECTOR_TILE'],
- sources : [ShadowVolumeFS]
- });
- primitive._spStencil = ShaderProgram.fromCache({
- context : context,
- vertexShaderSource : vs,
- fragmentShaderSource : fs,
- attributeLocations : attributeLocations
- });
- fsSource = ShaderSource.replaceMain(fsSource, 'czm_non_pick_main');
- fsSource =
- fsSource + '\n' +
- 'void main() \n' +
- '{ \n' +
- ' czm_non_pick_main(); \n' +
- ' gl_FragColor = ' + pickId + '; \n' +
- '} \n';
- var pickVS = new ShaderSource({
- sources : [vsSource]
- });
- var pickFS = new ShaderSource({
- defines : ['VECTOR_TILE'],
- sources : [fsSource]
- });
- primitive._spPick = ShaderProgram.fromCache({
- context : context,
- vertexShaderSource : pickVS,
- fragmentShaderSource : pickFS,
- attributeLocations : attributeLocations
- });
- }
- function getStencilPreloadRenderState(mask3DTiles) {
- var stencilFunction = mask3DTiles ? StencilFunction.EQUAL : StencilFunction.ALWAYS;
- return {
- colorMask : {
- red : false,
- green : false,
- blue : false,
- alpha : false
- },
- stencilTest : {
- enabled : true,
- frontFunction : stencilFunction,
- frontOperation : {
- fail : StencilOperation.KEEP,
- zFail : StencilOperation.DECREMENT_WRAP,
- zPass : StencilOperation.DECREMENT_WRAP
- },
- backFunction : stencilFunction,
- backOperation : {
- fail : StencilOperation.KEEP,
- zFail : StencilOperation.INCREMENT_WRAP,
- zPass : StencilOperation.INCREMENT_WRAP
- },
- reference : StencilConstants.CESIUM_3D_TILE_MASK,
- mask : StencilConstants.CESIUM_3D_TILE_MASK
- },
- stencilMask : StencilConstants.CLASSIFICATION_MASK,
- depthTest : {
- enabled : false
- },
- depthMask : false
- };
- }
- function getStencilDepthRenderState(mask3DTiles) {
- var stencilFunction = mask3DTiles ? StencilFunction.EQUAL : StencilFunction.ALWAYS;
- return {
- colorMask : {
- red : false,
- green : false,
- blue : false,
- alpha : false
- },
- stencilTest : {
- enabled : true,
- frontFunction : stencilFunction,
- frontOperation : {
- fail : StencilOperation.KEEP,
- zFail : StencilOperation.KEEP,
- zPass : StencilOperation.INCREMENT_WRAP
- },
- backFunction : stencilFunction,
- backOperation : {
- fail : StencilOperation.KEEP,
- zFail : StencilOperation.KEEP,
- zPass : StencilOperation.DECREMENT_WRAP
- },
- reference : StencilConstants.CESIUM_3D_TILE_MASK,
- mask : StencilConstants.CESIUM_3D_TILE_MASK
- },
- stencilMask : StencilConstants.CLASSIFICATION_MASK,
- depthTest : {
- enabled : true,
- func : DepthFunction.LESS_OR_EQUAL
- },
- depthMask : false
- };
- }
- var colorRenderState = {
- stencilTest : {
- enabled : true,
- frontFunction : StencilFunction.NOT_EQUAL,
- frontOperation : {
- fail : StencilOperation.KEEP,
- zFail : StencilOperation.KEEP,
- zPass : StencilOperation.DECREMENT_WRAP
- },
- backFunction : StencilFunction.NOT_EQUAL,
- backOperation : {
- fail : StencilOperation.KEEP,
- zFail : StencilOperation.KEEP,
- zPass : StencilOperation.DECREMENT_WRAP
- },
- reference : 0,
- mask : StencilConstants.CLASSIFICATION_MASK
- },
- stencilMask : StencilConstants.CLASSIFICATION_MASK,
- depthTest : {
- enabled : false
- },
- depthMask : false,
- blending : BlendingState.ALPHA_BLEND
- };
- var pickRenderState = {
- stencilTest : {
- enabled : true,
- frontFunction : StencilFunction.NOT_EQUAL,
- frontOperation : {
- fail : StencilOperation.KEEP,
- zFail : StencilOperation.KEEP,
- zPass : StencilOperation.DECREMENT_WRAP
- },
- backFunction : StencilFunction.NOT_EQUAL,
- backOperation : {
- fail : StencilOperation.KEEP,
- zFail : StencilOperation.KEEP,
- zPass : StencilOperation.DECREMENT_WRAP
- },
- reference : 0,
- mask : StencilConstants.CLASSIFICATION_MASK
- },
- stencilMask : StencilConstants.CLASSIFICATION_MASK,
- depthTest : {
- enabled : false
- },
- depthMask : false
- };
- function createRenderStates(primitive) {
- if (defined(primitive._rsStencilPreloadPass)) {
- return;
- }
- primitive._rsStencilPreloadPass = RenderState.fromCache(getStencilPreloadRenderState(false));
- primitive._rsStencilPreloadPass3DTiles = RenderState.fromCache(getStencilPreloadRenderState(true));
- primitive._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(false));
- primitive._rsStencilDepthPass3DTiles = RenderState.fromCache(getStencilDepthRenderState(true));
- primitive._rsColorPass = RenderState.fromCache(colorRenderState);
- primitive._rsPickPass = RenderState.fromCache(pickRenderState);
- }
- var modifiedModelViewScratch = new Matrix4();
- var rtcScratch = new Cartesian3();
- function createUniformMap(primitive, context) {
- if (defined(primitive._uniformMap)) {
- return;
- }
- var uniformMap = {
- u_modifiedModelViewProjection : function() {
- var viewMatrix = context.uniformState.view;
- var projectionMatrix = context.uniformState.projection;
- Matrix4.clone(viewMatrix, modifiedModelViewScratch);
- Matrix4.multiplyByPoint(modifiedModelViewScratch, primitive._center, rtcScratch);
- Matrix4.setTranslation(modifiedModelViewScratch, rtcScratch, modifiedModelViewScratch);
- Matrix4.multiply(projectionMatrix, modifiedModelViewScratch, modifiedModelViewScratch);
- return modifiedModelViewScratch;
- },
- u_highlightColor : function() {
- return primitive._highlightColor;
- }
- };
- primitive._uniformMap = primitive._batchTable.getUniformMapCallback()(uniformMap);
- }
- function copyIndicesCPU(indices, newIndices, currentOffset, offsets, counts, batchIds, batchIdLookUp) {
- var sizeInBytes = indices.constructor.BYTES_PER_ELEMENT;
- var batchedIdsLength = batchIds.length;
- for (var j = 0; j < batchedIdsLength; ++j) {
- var batchedId = batchIds[j];
- var index = batchIdLookUp[batchedId];
- var offset = offsets[index];
- var count = counts[index];
- var subarray = new indices.constructor(indices.buffer, sizeInBytes * offset, count);
- newIndices.set(subarray, currentOffset);
- offsets[index] = currentOffset;
- currentOffset += count;
- }
- return currentOffset;
- }
- function rebatchCPU(primitive, batchedIndices) {
- var indices = primitive._indices;
- var indexOffsets = primitive._indexOffsets;
- var indexCounts = primitive._indexCounts;
- var batchIdLookUp = primitive._batchIdLookUp;
- var newIndices = new indices.constructor(indices.length);
- var current = batchedIndices.pop();
- var newBatchedIndices = [current];
- var currentOffset = copyIndicesCPU(indices, newIndices, 0, indexOffsets, indexCounts, current.batchIds, batchIdLookUp);
- current.offset = 0;
- current.count = currentOffset;
- while (batchedIndices.length > 0) {
- var next = batchedIndices.pop();
- if (Color.equals(next.color, current.color)) {
- currentOffset = copyIndicesCPU(indices, newIndices, currentOffset, indexOffsets, indexCounts, next.batchIds, batchIdLookUp);
- current.batchIds = current.batchIds.concat(next.batchIds);
- current.count = currentOffset - current.offset;
- } else {
- var offset = currentOffset;
- currentOffset = copyIndicesCPU(indices, newIndices, currentOffset, indexOffsets, indexCounts, next.batchIds, batchIdLookUp);
- next.offset = offset;
- next.count = currentOffset - offset;
- newBatchedIndices.push(next);
- current = next;
- }
- }
- primitive._va.indexBuffer.copyFromArrayView(newIndices);
- primitive._indices = newIndices;
- primitive._batchedIndices = newBatchedIndices;
- }
- function copyIndicesGPU(readBuffer, writeBuffer, currentOffset, offsets, counts, batchIds, batchIdLookUp) {
- var sizeInBytes = readBuffer.bytesPerIndex;
- var batchedIdsLength = batchIds.length;
- for (var j = 0; j < batchedIdsLength; ++j) {
- var batchedId = batchIds[j];
- var index = batchIdLookUp[batchedId];
- var offset = offsets[index];
- var count = counts[index];
- writeBuffer.copyFromBuffer(readBuffer, offset * sizeInBytes, currentOffset * sizeInBytes, count * sizeInBytes);
- offsets[index] = currentOffset;
- currentOffset += count;
- }
- return currentOffset;
- }
- function rebatchGPU(primitive, batchedIndices) {
- var indexOffsets = primitive._indexOffsets;
- var indexCounts = primitive._indexCounts;
- var batchIdLookUp = primitive._batchIdLookUp;
- var current = batchedIndices.pop();
- var newBatchedIndices = [current];
- var readBuffer = primitive._va.indexBuffer;
- var writeBuffer = primitive._vaSwap.indexBuffer;
- var currentOffset = copyIndicesGPU(readBuffer, writeBuffer, 0, indexOffsets, indexCounts, current.batchIds, batchIdLookUp);
- current.offset = 0;
- current.count = currentOffset;
- while (batchedIndices.length > 0) {
- var next = batchedIndices.pop();
- if (Color.equals(next.color, current.color)) {
- currentOffset = copyIndicesGPU(readBuffer, writeBuffer, currentOffset, indexOffsets, indexCounts, next.batchIds, batchIdLookUp);
- current.batchIds = current.batchIds.concat(next.batchIds);
- current.count = currentOffset - current.offset;
- } else {
- var offset = currentOffset;
- currentOffset = copyIndicesGPU(readBuffer, writeBuffer, currentOffset, indexOffsets, indexCounts, next.batchIds, batchIdLookUp);
- next.offset = offset;
- next.count = currentOffset - offset;
- newBatchedIndices.push(next);
- current = next;
- }
- }
- var temp = primitive._va;
- primitive._va = primitive._vaSwap;
- primitive._vaSwap = temp;
- primitive._batchedIndices = newBatchedIndices;
- }
- function compareColors(a, b) {
- return b.color.toRgba() - a.color.toRgba();
- }
- // PERFORMANCE_IDEA: For WebGL 2, we can use copyBufferSubData for buffer-to-buffer copies.
- // PERFORMANCE_IDEA: Not supported, but we could use glMultiDrawElements here.
- function rebatchCommands(primitive, context) {
- if (!primitive._batchDirty) {
- return false;
- }
- var batchedIndices = primitive._batchedIndices;
- var length = batchedIndices.length;
- var needToRebatch = false;
- var colorCounts = {};
- for (var i = 0; i < length; ++i) {
- var color = batchedIndices[i].color;
- var rgba = color.toRgba();
- if (defined(colorCounts[rgba])) {
- needToRebatch = true;
- break;
- } else {
- colorCounts[rgba] = true;
- }
- }
- if (!needToRebatch) {
- primitive._batchDirty = false;
- return false;
- }
- if (needToRebatch && !primitive.forceRebatch && primitive._framesSinceLastRebatch < 120) {
- ++primitive._framesSinceLastRebatch;
- return;
- }
- batchedIndices.sort(compareColors);
- if (context.webgl2) {
- rebatchGPU(primitive, batchedIndices);
- } else {
- rebatchCPU(primitive, batchedIndices);
- }
- primitive._framesSinceLastRebatch = 0;
- primitive._batchDirty = false;
- primitive._pickCommandsDirty = true;
- primitive._wireframeDirty = true;
- return true;
- }
- function createColorCommands(primitive, context) {
- var needsRebatch = rebatchCommands(primitive, context);
- var commands = primitive._commands;
- var batchedIndices = primitive._batchedIndices;
- var length = batchedIndices.length;
- var commandsLength = length * 3;
- if (defined(commands) &&
- !needsRebatch &&
- commands.length === commandsLength) {
- return;
- }
- commands.length = commandsLength;
- var vertexArray = primitive._va;
- var sp = primitive._sp;
- var modelMatrix = defaultValue(primitive._modelMatrix, Matrix4.IDENTITY);
- var uniformMap = primitive._uniformMap;
- var bv = primitive._boundingVolume;
- for (var j = 0; j < length; ++j) {
- var offset = batchedIndices[j].offset;
- var count = batchedIndices[j].count;
- var stencilPreloadCommand = commands[j * 3];
- if (!defined(stencilPreloadCommand)) {
- stencilPreloadCommand = commands[j * 3] = new DrawCommand({
- owner : primitive
- });
- }
- stencilPreloadCommand.vertexArray = vertexArray;
- stencilPreloadCommand.modelMatrix = modelMatrix;
- stencilPreloadCommand.offset = offset;
- stencilPreloadCommand.count = count;
- stencilPreloadCommand.renderState = primitive._rsStencilPreloadPass;
- stencilPreloadCommand.shaderProgram = sp;
- stencilPreloadCommand.uniformMap = uniformMap;
- stencilPreloadCommand.boundingVolume = bv;
- stencilPreloadCommand.cull = false;
- stencilPreloadCommand.pass = Pass.TERRAIN_CLASSIFICATION;
- var stencilPreloadDerivedCommand = DrawCommand.shallowClone(stencilPreloadCommand, stencilPreloadCommand.derivedCommands.tileset);
- stencilPreloadDerivedCommand.renderState = primitive._rsStencilPreloadPass3DTiles;
- stencilPreloadDerivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;
- stencilPreloadCommand.derivedCommands.tileset = stencilPreloadDerivedCommand;
- var stencilDepthCommand = commands[j * 3 + 1];
- if (!defined(stencilDepthCommand)) {
- stencilDepthCommand = commands[j * 3 + 1] = new DrawCommand({
- owner : primitive
- });
- }
- stencilDepthCommand.vertexArray = vertexArray;
- stencilDepthCommand.modelMatrix = modelMatrix;
- stencilDepthCommand.offset = offset;
- stencilDepthCommand.count = count;
- stencilDepthCommand.renderState = primitive._rsStencilDepthPass;
- stencilDepthCommand.shaderProgram = sp;
- stencilDepthCommand.uniformMap = uniformMap;
- stencilDepthCommand.boundingVolume = bv;
- stencilDepthCommand.cull = false;
- stencilDepthCommand.pass = Pass.TERRAIN_CLASSIFICATION;
- var stencilDepthDerivedCommand = DrawCommand.shallowClone(stencilDepthCommand, stencilDepthCommand.derivedCommands.tileset);
- stencilDepthDerivedCommand.renderState = primitive._rsStencilDepthPass3DTiles;
- stencilDepthDerivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;
- stencilDepthCommand.derivedCommands.tileset = stencilDepthDerivedCommand;
- var colorCommand = commands[j * 3 + 2];
- if (!defined(colorCommand)) {
- colorCommand = commands[j * 3 + 2] = new DrawCommand({
- owner : primitive
- });
- }
- colorCommand.vertexArray = vertexArray;
- colorCommand.modelMatrix = modelMatrix;
- colorCommand.offset = offset;
- colorCommand.count = count;
- colorCommand.renderState = primitive._rsColorPass;
- colorCommand.shaderProgram = sp;
- colorCommand.uniformMap = uniformMap;
- colorCommand.boundingVolume = bv;
- colorCommand.cull = false;
- colorCommand.pass = Pass.TERRAIN_CLASSIFICATION;
- var colorDerivedCommand = DrawCommand.shallowClone(colorCommand, colorCommand.derivedCommands.tileset);
- colorDerivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;
- colorCommand.derivedCommands.tileset = colorDerivedCommand;
- }
- primitive._commandsDirty = true;
- }
- function createColorCommandsIgnoreShow(primitive, frameState) {
- if (primitive.classificationType === ClassificationType.TERRAIN ||
- !frameState.invertClassification ||
- (defined(primitive._commandsIgnoreShow) && !primitive._commandsDirty)) {
- return;
- }
- var commands = primitive._commands;
- var commandsIgnoreShow = primitive._commandsIgnoreShow;
- var spStencil = primitive._spStencil;
- var commandsLength = commands.length;
- var length = commandsIgnoreShow.length = commandsLength / 3 * 2;
- var commandIndex = 0;
- for (var j = 0; j < length; j += 2) {
- var commandIgnoreShow = commandsIgnoreShow[j] = DrawCommand.shallowClone(commands[commandIndex], commandsIgnoreShow[j]);
- commandIgnoreShow.shaderProgram = spStencil;
- commandIgnoreShow.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW;
- commandIgnoreShow = commandsIgnoreShow[j + 1] = DrawCommand.shallowClone(commands[commandIndex + 1], commandsIgnoreShow[j + 1]);
- commandIgnoreShow.shaderProgram = spStencil;
- commandIgnoreShow.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW;
- commandIndex += 3;
- }
- primitive._commandsDirty = false;
- }
- function createPickCommands(primitive) {
- if (!primitive._pickCommandsDirty) {
- return;
- }
- var length = primitive._indexOffsets.length;
- var pickCommands = primitive._pickCommands;
- pickCommands.length = length * 3;
- var vertexArray = primitive._va;
- var spStencil = primitive._spStencil;
- var spPick = primitive._spPick;
- var modelMatrix = defaultValue(primitive._modelMatrix, Matrix4.IDENTITY);
- var uniformMap = primitive._uniformMap;
- for (var j = 0; j < length; ++j) {
- var offset = primitive._indexOffsets[j];
- var count = primitive._indexCounts[j];
- var bv = defined(primitive._boundingVolumes) ? primitive._boundingVolumes[j] : primitive.boundingVolume;
- var stencilPreloadCommand = pickCommands[j * 3];
- if (!defined(stencilPreloadCommand)) {
- stencilPreloadCommand = pickCommands[j * 3] = new DrawCommand({
- owner : primitive,
- pickOnly : true
- });
- }
- stencilPreloadCommand.vertexArray = vertexArray;
- stencilPreloadCommand.modelMatrix = modelMatrix;
- stencilPreloadCommand.offset = offset;
- stencilPreloadCommand.count = count;
- stencilPreloadCommand.renderState = primitive._rsStencilPreloadPass;
- stencilPreloadCommand.shaderProgram = spStencil;
- stencilPreloadCommand.uniformMap = uniformMap;
- stencilPreloadCommand.boundingVolume = bv;
- stencilPreloadCommand.pass = Pass.TERRAIN_CLASSIFICATION;
- var stencilPreloadDerivedCommand = DrawCommand.shallowClone(stencilPreloadCommand, stencilPreloadCommand.derivedCommands.tileset);
- stencilPreloadDerivedCommand.renderState = primitive._rsStencilPreloadPass3DTiles;
- stencilPreloadDerivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;
- stencilPreloadCommand.derivedCommands.tileset = stencilPreloadDerivedCommand;
- var stencilDepthCommand = pickCommands[j * 3 + 1];
- if (!defined(stencilDepthCommand)) {
- stencilDepthCommand = pickCommands[j * 3 + 1] = new DrawCommand({
- owner : primitive,
- pickOnly : true
- });
- }
- stencilDepthCommand.vertexArray = vertexArray;
- stencilDepthCommand.modelMatrix = modelMatrix;
- stencilDepthCommand.offset = offset;
- stencilDepthCommand.count = count;
- stencilDepthCommand.renderState = primitive._rsStencilDepthPass;
- stencilDepthCommand.shaderProgram = spStencil;
- stencilDepthCommand.uniformMap = uniformMap;
- stencilDepthCommand.boundingVolume = bv;
- stencilDepthCommand.pass = Pass.TERRAIN_CLASSIFICATION;
- var stencilDepthDerivedCommand = DrawCommand.shallowClone(stencilDepthCommand, stencilDepthCommand.derivedCommands.tileset);
- stencilDepthDerivedCommand.renderState = primitive._rsStencilDepthPass3DTiles;
- stencilDepthDerivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;
- stencilDepthCommand.derivedCommands.tileset = stencilDepthDerivedCommand;
- var colorCommand = pickCommands[j * 3 + 2];
- if (!defined(colorCommand)) {
- colorCommand = pickCommands[j * 3 + 2] = new DrawCommand({
- owner : primitive,
- pickOnly : true
- });
- }
- colorCommand.vertexArray = vertexArray;
- colorCommand.modelMatrix = modelMatrix;
- colorCommand.offset = offset;
- colorCommand.count = count;
- colorCommand.renderState = primitive._rsPickPass;
- colorCommand.shaderProgram = spPick;
- colorCommand.uniformMap = uniformMap;
- colorCommand.boundingVolume = bv;
- colorCommand.pass = Pass.TERRAIN_CLASSIFICATION;
- var colorDerivedCommand = DrawCommand.shallowClone(colorCommand, colorCommand.derivedCommands.tileset);
- colorDerivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;
- colorCommand.derivedCommands.tileset = colorDerivedCommand;
- }
- primitive._pickCommandsDirty = false;
- }
- /**
- * Creates features for each mesh and places it at the batch id index of features.
- *
- * @param {Vector3DTileContent} content The vector tile content.
- * @param {Cesium3DTileFeature[]} features An array of features where the polygon features will be placed.
- */
- Vector3DTilePrimitive.prototype.createFeatures = function(content, features) {
- var batchIds = this._batchIds;
- var length = batchIds.length;
- for (var i = 0; i < length; ++i) {
- var batchId = batchIds[i];
- features[batchId] = new Cesium3DTileFeature(content, batchId);
- }
- };
- /**
- * Colors the entire tile when enabled is true. The resulting color will be (mesh batch table color * color).
- *
- * @param {Boolean} enabled Whether to enable debug coloring.
- * @param {Color} color The debug color.
- */
- Vector3DTilePrimitive.prototype.applyDebugSettings = function(enabled, color) {
- this._highlightColor = enabled ? color : this._constantColor;
- };
- function clearStyle(polygons, features) {
- polygons._updatingAllCommands = true;
- var batchIds = polygons._batchIds;
- var length = batchIds.length;
- var i;
- for (i = 0; i < length; ++i) {
- var batchId = batchIds[i];
- var feature = features[batchId];
- feature.show = true;
- feature.color = Color.WHITE;
- }
- var batchedIndices = polygons._batchedIndices;
- length = batchedIndices.length;
- for (i = 0; i < length; ++i) {
- batchedIndices[i].color = Color.clone(Color.WHITE);
- }
- polygons._updatingAllCommands = false;
- polygons._batchDirty = true;
- }
- var scratchColor = new Color();
- var DEFAULT_COLOR_VALUE = Color.WHITE;
- var DEFAULT_SHOW_VALUE = true;
- var complexExpressionReg = /\$/;
- /**
- * Apply a style to the content.
- *
- * @param {Cesium3DTileStyle} style The style.
- * @param {Cesium3DTileFeature[]} features The array of features.
- */
- Vector3DTilePrimitive.prototype.applyStyle = function(style, features) {
- if (!defined(style)) {
- clearStyle(this, features);
- return;
- }
- var colorExpression = style.color;
- var isSimpleStyle = colorExpression instanceof Expression && !complexExpressionReg.test(colorExpression.expression);
- this._updatingAllCommands = isSimpleStyle;
- var batchIds = this._batchIds;
- var length = batchIds.length;
- var i;
- for (i = 0; i < length; ++i) {
- var batchId = batchIds[i];
- var feature = features[batchId];
- feature.color = defined(style.color) ? style.color.evaluateColor(feature, scratchColor) : DEFAULT_COLOR_VALUE;
- feature.show = defined(style.show) ? style.show.evaluate(feature) : DEFAULT_SHOW_VALUE;
- }
- if (isSimpleStyle) {
- var batchedIndices = this._batchedIndices;
- length = batchedIndices.length;
- for (i = 0; i < length; ++i) {
- batchedIndices[i].color = Color.clone(Color.WHITE);
- }
- this._updatingAllCommands = false;
- this._batchDirty = true;
- }
- };
- /**
- * Call when updating the color of a mesh with batchId changes color. The meshes will need to be re-batched
- * on the next update.
- *
- * @param {Number} batchId The batch id of the meshes whose color has changed.
- * @param {Color} color The new polygon color.
- */
- Vector3DTilePrimitive.prototype.updateCommands = function(batchId, color) {
- if (this._updatingAllCommands) {
- return;
- }
- var batchIdLookUp = this._batchIdLookUp;
- var index = batchIdLookUp[batchId];
- if (!defined(index)) {
- return;
- }
- var indexOffsets = this._indexOffsets;
- var indexCounts = this._indexCounts;
- var offset = indexOffsets[index];
- var count = indexCounts[index];
- var batchedIndices = this._batchedIndices;
- var length = batchedIndices.length;
- var i;
- for (i = 0; i < length; ++i) {
- var batchedOffset = batchedIndices[i].offset;
- var batchedCount = batchedIndices[i].count;
- if (offset >= batchedOffset && offset < batchedOffset + batchedCount) {
- break;
- }
- }
- batchedIndices.push(new Vector3DTileBatch({
- color : Color.clone(color),
- offset : offset,
- count : count,
- batchIds : [batchId]
- }));
- var startIds = [];
- var endIds = [];
- var batchIds = batchedIndices[i].batchIds;
- var batchIdsLength = batchIds.length;
- for (var j = 0; j < batchIdsLength; ++j) {
- var id = batchIds[j];
- if (id === batchId) {
- continue;
- }
- var offsetIndex = batchIdLookUp[id];
- if (indexOffsets[offsetIndex] < offset) {
- startIds.push(id);
- } else {
- endIds.push(id);
- }
- }
- if (endIds.length !== 0) {
- batchedIndices.push(new Vector3DTileBatch({
- color : Color.clone(batchedIndices[i].color),
- offset : offset + count,
- count : batchedIndices[i].offset + batchedIndices[i].count - (offset + count),
- batchIds : endIds
- }));
- }
- if (startIds.length !== 0) {
- batchedIndices[i].count = offset - batchedIndices[i].offset;
- batchedIndices[i].batchIds = startIds;
- } else {
- batchedIndices.splice(i, 1);
- }
- this._batchDirty = true;
- };
- function queueCommands(primitive, frameState, commands, commandsIgnoreShow) {
- var classificationType = primitive.classificationType;
- var queueTerrainCommands = (classificationType !== ClassificationType.CESIUM_3D_TILE);
- var queue3DTilesCommands = (classificationType !== ClassificationType.TERRAIN);
- var commandList = frameState.commandList;
- var commandLength = commands.length;
- var command;
- var i;
- for (i = 0; i < commandLength; ++i) {
- if (queueTerrainCommands) {
- command = commands[i];
- command.pass = Pass.TERRAIN_CLASSIFICATION;
- commandList.push(command);
- }
- if (queue3DTilesCommands) {
- command = commands[i].derivedCommands.tileset;
- command.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;
- commandList.push(command);
- }
- }
- if (!frameState.invertClassification || !defined(commandsIgnoreShow)) {
- return;
- }
- commandLength = commandsIgnoreShow.length;
- for (i = 0; i < commandLength; ++i) {
- commandList.push(commandsIgnoreShow[i]);
- }
- }
- function queueWireframeCommands(frameState, commands) {
- var commandList = frameState.commandList;
- var commandLength = commands.length;
- for (var i = 0; i < commandLength; i += 3) {
- var command = commands[i + 2];
- command.pass = Pass.OPAQUE;
- commandList.push(command);
- }
- }
- function updateWireframe(primitive) {
- var earlyExit = primitive.debugWireframe === primitive._debugWireframe;
- earlyExit = earlyExit && !(primitive.debugWireframe && primitive._wireframeDirty);
- if (earlyExit) {
- return;
- }
- if (!defined(primitive._rsWireframe)) {
- primitive._rsWireframe = RenderState.fromCache({});
- }
- var rs;
- var type;
- if (primitive.debugWireframe) {
- rs = primitive._rsWireframe;
- type = PrimitiveType.LINES;
- } else {
- rs = primitive._rsColorPass;
- type = PrimitiveType.TRIANGLES;
- }
- var commands = primitive._commands;
- var commandLength = commands.length;
- for (var i = 0; i < commandLength; i += 3) {
- var command = commands[i + 2];
- command.renderState = rs;
- command.primitiveType = type;
- }
- primitive._debugWireframe = primitive.debugWireframe;
- primitive._wireframeDirty = false;
- }
- /**
- * Updates the batches and queues the commands for rendering.
- *
- * @param {FrameState} frameState The current frame state.
- */
- Vector3DTilePrimitive.prototype.update = function(frameState) {
- var context = frameState.context;
- createVertexArray(this, context);
- createShaders(this, context);
- createRenderStates(this);
- createUniformMap(this, context);
- var passes = frameState.passes;
- if (passes.render) {
- createColorCommands(this, context);
- createColorCommandsIgnoreShow(this, frameState);
- updateWireframe(this);
- if (this._debugWireframe) {
- queueWireframeCommands(frameState, this._commands);
- } else {
- queueCommands(this, frameState, this._commands, this._commandsIgnoreShow);
- }
- }
- if (passes.pick) {
- createPickCommands(this);
- queueCommands(this, frameState, this._pickCommands);
- }
- };
- /**
- * Returns true if this object was destroyed; otherwise, false.
- * <p>
- * If this object was destroyed, it should not be used; calling any function other than
- * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
- * </p>
- *
- * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
- */
- Vector3DTilePrimitive.prototype.isDestroyed = function() {
- return false;
- };
- /**
- * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
- * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
- * <p>
- * Once an object is destroyed, it should not be used; calling any function other than
- * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
- * assign the return value (<code>undefined</code>) to the object as done in the example.
- * </p>
- *
- * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
- */
- Vector3DTilePrimitive.prototype.destroy = function() {
- this._va = this._va && this._va.destroy();
- this._sp = this._sp && this._sp.destroy();
- this._spPick = this._spPick && this._spPick.destroy();
- this._vaSwap = this._vaSwap && this._vaSwap.destroy();
- return destroyObject(this);
- };
- export default Vector3DTilePrimitive;
|