From 06f133bf55c800272a38c3908ae6404ff2168bf6 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Fri, 14 Dec 2018 17:33:18 -0500 Subject: [PATCH 01/39] Set 3D Tiles stencil bit --- Source/Scene/Cesium3DTileBatchTable.js | 91 +++++++++++++++-------- Source/Scene/Cesium3DTileset.js | 21 ++++-- Source/Scene/Cesium3DTilesetTraversal.js | 8 +- Source/Scene/ClassificationPrimitive.js | 36 ++++----- Source/Scene/GlobeSurfaceTileProvider.js | 14 ++-- Source/Scene/PointCloud.js | 10 ++- Source/Scene/PointCloudEyeDomeLighting.js | 6 +- Source/Scene/StencilConstants.js | 42 +++++++++++ 8 files changed, 157 insertions(+), 71 deletions(-) create mode 100644 Source/Scene/StencilConstants.js diff --git a/Source/Scene/Cesium3DTileBatchTable.js b/Source/Scene/Cesium3DTileBatchTable.js index de62af8f2ac4..316afc27f63b 100644 --- a/Source/Scene/Cesium3DTileBatchTable.js +++ b/Source/Scene/Cesium3DTileBatchTable.js @@ -31,6 +31,7 @@ define([ './Cesium3DTileColorBlendMode', './CullFace', './getBinaryAccessor', + './StencilConstants', './StencilFunction', './StencilOperation' ], function( @@ -66,6 +67,7 @@ define([ Cesium3DTileColorBlendMode, CullFace, getBinaryAccessor, + StencilConstants, StencilFunction, StencilOperation) { 'use strict'; @@ -1261,30 +1263,42 @@ define([ derivedCommands.originalCommand = deriveCommand(command); command.dirty = false; } + var originalCommand = derivedCommands.originalCommand; - if (styleCommandsNeeded !== StyleCommandsNeeded.ALL_OPAQUE) { + if (styleCommandsNeeded !== StyleCommandsNeeded.ALL_OPAQUE && command.pass !== Pass.TRANSLUCENT) { if (!defined(derivedCommands.translucent)) { - derivedCommands.translucent = deriveTranslucentCommand(derivedCommands.originalCommand); + derivedCommands.translucent = deriveTranslucentCommand(originalCommand); } } - if (bivariateVisibilityTest) { - if (command.pass !== Pass.TRANSLUCENT && !finalResolution) { - if (!defined(derivedCommands.zback)) { - derivedCommands.zback = deriveZBackfaceCommand(frameState.context, derivedCommands.originalCommand); - } - tileset._backfaceCommands.push(derivedCommands.zback); + if (styleCommandsNeeded !== StyleCommandsNeeded.ALL_TRANSLUCENT && command.pass !== Pass.TRANSLUCENT) { + if (!defined(derivedCommands.opaque)) { + derivedCommands.opaque = deriveOpaqueCommand(originalCommand); } - if (!defined(derivedCommands.stencil) || tile._selectionDepth !== getLastSelectionDepth(derivedCommands.stencil)) { - derivedCommands.stencil = deriveStencilCommand(derivedCommands.originalCommand, tile._selectionDepth); + + if (bivariateVisibilityTest) { + if (!finalResolution) { + if (!defined(derivedCommands.zback)) { + derivedCommands.zback = deriveZBackfaceCommand(frameState.context, originalCommand); + } + tileset._backfaceCommands.push(derivedCommands.zback); + } + if (!defined(derivedCommands.stencil) || (tile._selectionDepth !== getLastSelectionDepth(derivedCommands.stencil))) { + if (command.renderState.depthMask) { + derivedCommands.stencil = deriveStencilCommand(originalCommand, tile._selectionDepth); + } else { + // Ignore if tile does not write depth + derivedCommands.stencil = derivedCommands.opaque; + } + } } } - var opaqueCommand = bivariateVisibilityTest ? derivedCommands.stencil : derivedCommands.originalCommand; + var opaqueCommand = bivariateVisibilityTest ? derivedCommands.stencil : derivedCommands.opaque; var translucentCommand = derivedCommands.translucent; // If the command was originally opaque: - // * If the styling applied to the tile is all opaque, use the original command + // * If the styling applied to the tile is all opaque, use the opaque command // (with one additional uniform needed for the shader). // * If the styling is all translucent, use new (cached) derived commands (front // and back faces) with a translucent render state. @@ -1308,7 +1322,7 @@ define([ // as of now, a style can't change an originally translucent feature to // opaque since the style's alpha is modulated, not a replacement. When // this changes, we need to derive new opaque commands here. - commandList[i] = opaqueCommand; + commandList[i] = originalCommand; } } }; @@ -1348,6 +1362,12 @@ define([ return derivedCommand; } + function deriveOpaqueCommand(command) { + var derivedCommand = DrawCommand.shallowClone(command); + derivedCommand.renderState = getOpaqueRenderState(command.renderState); + return derivedCommand; + } + function getDisableLogDepthFragmentShaderProgram(context, shaderProgram) { var shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, 'zBackfaceLogDepth'); if (!defined(shader)) { @@ -1385,6 +1405,10 @@ define([ factor : 5.0, units : 5.0 }; + // Set the 3D Tiles bit + rs.stencilTest = StencilConstants.setCesium3DTileBit(); + rs.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK; + derivedCommand.renderState = RenderState.fromCache(rs); derivedCommand.castShadows = false; derivedCommand.receiveShadows = false; @@ -1395,27 +1419,26 @@ define([ } function deriveStencilCommand(command, reference) { - var derivedCommand = command; - if (command.renderState.depthMask) { // ignore if tile does not write depth (ex. translucent) - // Tiles only draw if their selection depth is >= the tile drawn already. They write their - // selection depth to the stencil buffer to prevent ancestor tiles from drawing on top - derivedCommand = DrawCommand.shallowClone(command); - var rs = clone(derivedCommand.renderState, true); - // Stencil test is masked to the most significant 4 bits so the reference is shifted. - // This is to prevent clearing the stencil before classification which needs the least significant - // bits for increment/decrement operations. - rs.stencilTest.enabled = true; - rs.stencilTest.mask = 0xF0; - rs.stencilTest.reference = reference << 4; - rs.stencilTest.frontFunction = StencilFunction.GREATER_OR_EQUAL; - rs.stencilTest.frontOperation.zPass = StencilOperation.REPLACE; - derivedCommand.renderState = RenderState.fromCache(rs); - } + // Tiles only draw if their selection depth is >= the tile drawn already. They write their + // selection depth to the stencil buffer to prevent ancestor tiles from drawing on top + var derivedCommand = DrawCommand.shallowClone(command); + var rs = clone(derivedCommand.renderState, true); + // Stencil test is masked to the most significant 3 bits so the reference is shifted. Writes 0 for the terrain bit + rs.stencilTest.enabled = true; + rs.stencilTest.mask = StencilConstants.SKIP_LOD_MASK; + rs.stencilTest.reference = StencilConstants.CESIUM_3D_TILE_MASK | (reference << StencilConstants.SKIP_LOD_BIT_SHIFT); + rs.stencilTest.frontFunction = StencilFunction.GREATER_OR_EQUAL; + rs.stencilTest.frontOperation.zPass = StencilOperation.REPLACE; + rs.stencilTest.backFunction = StencilFunction.GREATER_OR_EQUAL; + rs.stencilTest.backOperation.zPass = StencilOperation.REPLACE; + rs.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK | StencilConstants.SKIP_LOD_MASK; + derivedCommand.renderState = RenderState.fromCache(rs); return derivedCommand; } function getLastSelectionDepth(stencilCommand) { - return stencilCommand.renderState.stencilTest.reference >>> 4; + var reference = stencilCommand.renderState.stencilTest.reference; + return (reference & ~StencilConstants.CESIUM_3D_TILE_MASK) >>> StencilConstants.CESIUM_3D_TILE_BIT_SHIFT; } function getTranslucentRenderState(renderState) { @@ -1428,6 +1451,14 @@ define([ return RenderState.fromCache(rs); } + function getOpaqueRenderState(renderState) { + var rs = clone(renderState, true); + rs.stencilTest = StencilConstants.setCesium3DTileBit(); + rs.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK; + + return RenderState.fromCache(rs); + } + /////////////////////////////////////////////////////////////////////////// function createTexture(batchTable, context, bytes) { diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 8b394390f0b6..2ede14c245d3 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -22,6 +22,7 @@ define([ '../Core/Transforms', '../Renderer/ClearCommand', '../Renderer/Pass', + '../Renderer/RenderState', '../ThirdParty/when', './Axis', './Cesium3DTile', @@ -40,6 +41,7 @@ define([ './PointCloudShading', './SceneMode', './ShadowMode', + './StencilConstants', './TileBoundingRegion', './TileBoundingSphere', './TileOrientedBoundingBox' @@ -67,6 +69,7 @@ define([ Transforms, ClearCommand, Pass, + RenderState, when, Axis, Cesium3DTile, @@ -85,6 +88,7 @@ define([ PointCloudShading, SceneMode, ShadowMode, + StencilConstants, TileBoundingRegion, TileBoundingSphere, TileOrientedBoundingBox) { @@ -194,6 +198,7 @@ define([ this._hasMixedContent = false; + this._stencilClearCommand = undefined; this._backfaceCommands = new ManagedArray(); this._maximumScreenSpaceError = defaultValue(options.maximumScreenSpaceError, 16); @@ -1702,11 +1707,6 @@ define([ tileset._tileDebugLabels.update(frameState); } - var stencilClearCommand = new ClearCommand({ - stencil : 0, - pass : Pass.CESIUM_3D_TILE - }); - function updateTiles(tileset, frameState) { tileset._styleEngine.applyStyle(tileset, frameState); @@ -1728,7 +1728,16 @@ define([ tileset._backfaceCommands.length = 0; if (bivariateVisibilityTest) { - commandList.push(stencilClearCommand); + if (!defined(tileset._stencilClearCommand)) { + tileset._stencilClearCommand = new ClearCommand({ + stencil : 0, + pass : Pass.CESIUM_3D_TILE, + renderState : RenderState.fromCache({ + stencilMask : StencilConstants.SKIP_LOD_MASK + }) + }); + } + commandList.push(tileset._stencilClearCommand); } var lengthBeforeUpdate = commandList.length; diff --git a/Source/Scene/Cesium3DTilesetTraversal.js b/Source/Scene/Cesium3DTilesetTraversal.js index e9c0a0e962fe..654b7639b9b9 100644 --- a/Source/Scene/Cesium3DTilesetTraversal.js +++ b/Source/Scene/Cesium3DTilesetTraversal.js @@ -527,12 +527,8 @@ define([ * the children's z-depth and the ancestor's z-depth. We cannot rely on Z because we want the child to appear on top * of ancestor regardless of true depth. The stencil tests used require children to be drawn first. * - * NOTE: this will no longer work when there is a chain of selected tiles that is longer than the size of the - * stencil buffer (usually 8 bits). In other words, the subset of the tree containing only selected tiles must be - * no deeper than 255. It is very, very unlikely this will cause a problem. - * - * NOTE: when the scene has inverted classification enabled, the stencil buffer will be masked to 4 bits. So, the - * selected tiles must be no deeper than 15. This is still very unlikely. + * NOTE: 3D Tiles uses 3 bits from the stencil buffer meaning this will not work when there is a chain of + * selected tiles that is deeper than 7. This is not very likely. */ function traverseAndSelect(tileset, root, frameState) { var stack = selectionTraversal.stack; diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js index bc5b8614e469..57502e5290da 100644 --- a/Source/Scene/ClassificationPrimitive.js +++ b/Source/Scene/ClassificationPrimitive.js @@ -23,6 +23,7 @@ define([ './Primitive', './SceneMode', './ShadowVolumeAppearance', + './StencilConstants', './StencilFunction', './StencilOperation' ], function( @@ -50,6 +51,7 @@ define([ Primitive, SceneMode, ShadowVolumeAppearance, + StencilConstants, StencilFunction, StencilOperation) { 'use strict'; @@ -379,12 +381,6 @@ define([ return scene.context.stencilBuffer; }; - // The stencil mask only uses the least significant 4 bits. - // This is so 3D Tiles with the skip LOD optimization, which uses the most significant 4 bits, - // can be classified. - var stencilMask = 0x0F; - var stencilReference = 0; - function getStencilPreloadRenderState(enableStencil) { return { colorMask : { @@ -395,21 +391,22 @@ define([ }, stencilTest : { enabled : enableStencil, - frontFunction : StencilFunction.ALWAYS, + frontFunction : StencilFunction.EQUAL, frontOperation : { fail : StencilOperation.KEEP, zFail : StencilOperation.DECREMENT_WRAP, zPass : StencilOperation.DECREMENT_WRAP }, - backFunction : StencilFunction.ALWAYS, + backFunction : StencilFunction.EQUAL, backOperation : { fail : StencilOperation.KEEP, zFail : StencilOperation.INCREMENT_WRAP, zPass : StencilOperation.INCREMENT_WRAP }, - reference : stencilReference, - mask : stencilMask + reference : ~0, + mask : StencilConstants.CESIUM_3D_TILE_MASK }, + stencilMask : StencilConstants.CLASSIFICATION_MASK, depthTest : { enabled : false }, @@ -427,21 +424,22 @@ define([ }, stencilTest : { enabled : enableStencil, - frontFunction : StencilFunction.ALWAYS, + frontFunction : StencilFunction.EQUAL, frontOperation : { fail : StencilOperation.KEEP, zFail : StencilOperation.KEEP, zPass : StencilOperation.INCREMENT_WRAP }, - backFunction : StencilFunction.ALWAYS, + backFunction : StencilFunction.EQUAL, backOperation : { fail : StencilOperation.KEEP, zFail : StencilOperation.KEEP, zPass : StencilOperation.DECREMENT_WRAP }, - reference : stencilReference, - mask : stencilMask + reference : ~0, + mask : StencilConstants.CESIUM_3D_TILE_MASK }, + stencilMask : StencilConstants.CLASSIFICATION_MASK, depthTest : { enabled : true, func : DepthFunction.LESS_OR_EQUAL @@ -466,9 +464,10 @@ define([ zFail : StencilOperation.KEEP, zPass : StencilOperation.DECREMENT_WRAP }, - reference : stencilReference, - mask : stencilMask + reference : 0, + mask : StencilConstants.CLASSIFICATION_MASK }, + stencilMask : StencilConstants.CLASSIFICATION_MASK, depthTest : { enabled : false }, @@ -492,9 +491,10 @@ define([ zFail : StencilOperation.KEEP, zPass : StencilOperation.DECREMENT_WRAP }, - reference : stencilReference, - mask : stencilMask + reference : StencilConstants.NONE, + mask : StencilConstants.CLASSIFICATION_MASK }, + stencilMask : StencilConstants.CLASSIFICATION_MASK, depthTest : { enabled : false }, diff --git a/Source/Scene/GlobeSurfaceTileProvider.js b/Source/Scene/GlobeSurfaceTileProvider.js index 0117fdf3b1ad..29b0411c7d85 100644 --- a/Source/Scene/GlobeSurfaceTileProvider.js +++ b/Source/Scene/GlobeSurfaceTileProvider.js @@ -35,13 +35,13 @@ define([ '../Renderer/Pass', '../Renderer/RenderState', '../Renderer/VertexArray', - '../Scene/BlendingState', - '../Scene/DepthFunction', - '../Scene/PerInstanceColorAppearance', - '../Scene/Primitive', + './BlendingState', './ClippingPlaneCollection', + './DepthFunction', './GlobeSurfaceTile', './ImageryLayer', + './PerInstanceColorAppearance', + './Primitive', './QuadtreeTileLoadState', './SceneMode', './ShadowMode' @@ -83,12 +83,12 @@ define([ RenderState, VertexArray, BlendingState, - DepthFunction, - PerInstanceColorAppearance, - Primitive, ClippingPlaneCollection, + DepthFunction, GlobeSurfaceTile, ImageryLayer, + PerInstanceColorAppearance, + Primitive, QuadtreeTileLoadState, SceneMode, ShadowMode) { diff --git a/Source/Scene/PointCloud.js b/Source/Scene/PointCloud.js index 252764a23f4e..5bf917a6016c 100644 --- a/Source/Scene/PointCloud.js +++ b/Source/Scene/PointCloud.js @@ -38,7 +38,8 @@ define([ './getClipAndStyleCode', './getClippingFunction', './SceneMode', - './ShadowMode' + './ShadowMode', + './StencilConstants' ], function( arraySlice, BoundingSphere, @@ -79,7 +80,8 @@ define([ getClipAndStyleCode, getClippingFunction, SceneMode, - ShadowMode) { + ShadowMode, + StencilConstants) { 'use strict'; // Bail out if the browser doesn't support typed arrays, to prevent the setup function @@ -740,7 +742,9 @@ define([ pointCloud._opaqueRenderState = RenderState.fromCache({ depthTest : { enabled : true - } + }, + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK }); pointCloud._translucentRenderState = RenderState.fromCache({ diff --git a/Source/Scene/PointCloudEyeDomeLighting.js b/Source/Scene/PointCloudEyeDomeLighting.js index 16d5daa5d46b..e43c7230eda6 100644 --- a/Source/Scene/PointCloudEyeDomeLighting.js +++ b/Source/Scene/PointCloudEyeDomeLighting.js @@ -19,6 +19,7 @@ define([ '../Renderer/TextureMinificationFilter', '../Renderer/TextureWrap', '../Scene/BlendingState', + '../Scene/StencilConstants', '../Shaders/PostProcessStages/PointCloudEyeDomeLighting' ], function( Cartesian3, @@ -41,6 +42,7 @@ define([ TextureMinificationFilter, TextureWrap, BlendingState, + StencilConstants, PointCloudEyeDomeLightingShader) { 'use strict'; @@ -160,7 +162,9 @@ define([ depthMask : true, depthTest : { enabled : true - } + }, + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK }); processor._drawCommand = context.createViewportQuadCommand(blendFS, { diff --git a/Source/Scene/StencilConstants.js b/Source/Scene/StencilConstants.js new file mode 100644 index 000000000000..15dff3d46ab8 --- /dev/null +++ b/Source/Scene/StencilConstants.js @@ -0,0 +1,42 @@ +define([ + '../Core/freezeObject', + './StencilFunction', + './StencilOperation' + ], function( + freezeObject, + StencilFunction, + StencilOperation) { + 'use strict'; + + /** + * @private + */ + var StencilConstants = { + CESIUM_3D_TILE_MASK : 0x80, + SKIP_LOD_MASK : 0x70, + SKIP_LOD_BIT_SHIFT : 4, + CLASSIFICATION_MASK : 0x0F + }; + + StencilConstants.setCesium3DTileBit = function() { + return { + enabled : true, + frontFunction : StencilFunction.ALWAYS, + frontOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.REPLACE + }, + backFunction : StencilFunction.ALWAYS, + backOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.REPLACE + }, + reference : ~0, + mask : StencilConstants.CESIUM_3D_TILE_MASK + }; + }; + + return freezeObject(StencilConstants); +}); From 00e2d6af3c1e6b81706b0b1b12c6616b5e233e60 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Sun, 16 Dec 2018 17:50:44 -0500 Subject: [PATCH 02/39] Update ground primitive and classification primitive --- .../gallery/Classification Types.html | 1 - Source/Renderer/Pass.js | 9 +- Source/Scene/Cesium3DTileBatchTable.js | 3 +- Source/Scene/ClassificationPrimitive.js | 215 +++++++++++------- Source/Scene/GroundPrimitive.js | 126 +++++----- Source/Scene/InvertClassification.js | 18 +- Source/Scene/PointCloud.js | 15 +- Source/Scene/Scene.js | 31 +-- Source/Scene/StencilConstants.js | 6 +- Source/Scene/Vector3DTilePrimitive.js | 211 ++++++++++------- .../Shaders/Builtin/Constants/passOpaque.glsl | 2 +- .../Builtin/Constants/passOverlay.glsl | 2 +- .../Builtin/Constants/passTranslucent.glsl | 2 +- 13 files changed, 366 insertions(+), 275 deletions(-) diff --git a/Apps/Sandcastle/gallery/Classification Types.html b/Apps/Sandcastle/gallery/Classification Types.html index a874c9a8a687..f818b0c10787 100644 --- a/Apps/Sandcastle/gallery/Classification Types.html +++ b/Apps/Sandcastle/gallery/Classification Types.html @@ -30,7 +30,6 @@ var viewer = new Cesium.Viewer('cesiumContainer', { terrainProvider: Cesium.createWorldTerrain() }); -viewer.scene.globe.depthTestAgainstTerrain = false; var tileset = new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(6074) }); viewer.scene.primitives.add(tileset); diff --git a/Source/Renderer/Pass.js b/Source/Renderer/Pass.js index 3ab04a936286..f623fab44eec 100644 --- a/Source/Renderer/Pass.js +++ b/Source/Renderer/Pass.js @@ -24,11 +24,10 @@ define([ CESIUM_3D_TILE : 4, CESIUM_3D_TILE_CLASSIFICATION : 5, CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW : 6, - CLASSIFICATION : 7, - OPAQUE : 8, - TRANSLUCENT : 9, - OVERLAY : 10, - NUMBER_OF_PASSES : 11 + OPAQUE : 7, + TRANSLUCENT : 8, + OVERLAY : 9, + NUMBER_OF_PASSES : 10 }; return freezeObject(Pass); diff --git a/Source/Scene/Cesium3DTileBatchTable.js b/Source/Scene/Cesium3DTileBatchTable.js index 316afc27f63b..0b8807144ee8 100644 --- a/Source/Scene/Cesium3DTileBatchTable.js +++ b/Source/Scene/Cesium3DTileBatchTable.js @@ -1437,8 +1437,9 @@ define([ } function getLastSelectionDepth(stencilCommand) { + // Isolate the selection depth from the stencil reference. var reference = stencilCommand.renderState.stencilTest.reference; - return (reference & ~StencilConstants.CESIUM_3D_TILE_MASK) >>> StencilConstants.CESIUM_3D_TILE_BIT_SHIFT; + return (reference & StencilConstants.SKIP_LOD_MASK) >>> StencilConstants.SKIP_LOD_BIT_SHIFT; } function getTranslucentRenderState(renderState) { diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js index 57502e5290da..d2c1ca987238 100644 --- a/Source/Scene/ClassificationPrimitive.js +++ b/Source/Scene/ClassificationPrimitive.js @@ -182,7 +182,9 @@ define([ this._spColor2D = undefined; // only derived if necessary this._rsStencilPreloadPass = undefined; + this._rsStencilPreloadPass3DTiles = undefined; this._rsStencilDepthPass = undefined; + this._rsStencilDepthPass3DTiles = undefined; this._rsColorPass = undefined; this._rsPickPass = undefined; @@ -381,7 +383,8 @@ define([ return scene.context.stencilBuffer; }; - function getStencilPreloadRenderState(enableStencil) { + function getStencilPreloadRenderState(enableStencil, mask3DTiles) { + var stencilFunction = mask3DTiles ? StencilFunction.EQUAL : StencilFunction.ALWAYS; return { colorMask : { red : false, @@ -391,19 +394,19 @@ define([ }, stencilTest : { enabled : enableStencil, - frontFunction : StencilFunction.EQUAL, + frontFunction : stencilFunction, frontOperation : { fail : StencilOperation.KEEP, zFail : StencilOperation.DECREMENT_WRAP, zPass : StencilOperation.DECREMENT_WRAP }, - backFunction : StencilFunction.EQUAL, + backFunction : stencilFunction, backOperation : { fail : StencilOperation.KEEP, zFail : StencilOperation.INCREMENT_WRAP, zPass : StencilOperation.INCREMENT_WRAP }, - reference : ~0, + reference : StencilConstants.CESIUM_3D_TILE_MASK, mask : StencilConstants.CESIUM_3D_TILE_MASK }, stencilMask : StencilConstants.CLASSIFICATION_MASK, @@ -414,7 +417,8 @@ define([ }; } - function getStencilDepthRenderState(enableStencil) { + function getStencilDepthRenderState(enableStencil, mask3DTiles) { + var stencilFunction = mask3DTiles ? StencilFunction.EQUAL : StencilFunction.ALWAYS; return { colorMask : { red : false, @@ -424,19 +428,19 @@ define([ }, stencilTest : { enabled : enableStencil, - frontFunction : StencilFunction.EQUAL, + frontFunction : stencilFunction, frontOperation : { fail : StencilOperation.KEEP, zFail : StencilOperation.KEEP, zPass : StencilOperation.INCREMENT_WRAP }, - backFunction : StencilFunction.EQUAL, + backFunction : stencilFunction, backOperation : { fail : StencilOperation.KEEP, zFail : StencilOperation.KEEP, zPass : StencilOperation.DECREMENT_WRAP }, - reference : ~0, + reference : StencilConstants.CESIUM_3D_TILE_MASK, mask : StencilConstants.CESIUM_3D_TILE_MASK }, stencilMask : StencilConstants.CLASSIFICATION_MASK, @@ -491,7 +495,7 @@ define([ zFail : StencilOperation.KEEP, zPass : StencilOperation.DECREMENT_WRAP }, - reference : StencilConstants.NONE, + reference : 0, mask : StencilConstants.CLASSIFICATION_MASK }, stencilMask : StencilConstants.CLASSIFICATION_MASK, @@ -507,9 +511,11 @@ define([ } var stencilEnabled = !classificationPrimitive.debugShowShadowVolume; - classificationPrimitive._rsStencilPreloadPass = RenderState.fromCache(getStencilPreloadRenderState(stencilEnabled)); - classificationPrimitive._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(stencilEnabled)); - classificationPrimitive._rsColorPass = RenderState.fromCache(getColorRenderState(stencilEnabled)); + classificationPrimitive._rsStencilPreloadPass = RenderState.fromCache(getStencilPreloadRenderState(stencilEnabled, false)); + classificationPrimitive._rsStencilPreloadPass3DTiles = RenderState.fromCache(getStencilPreloadRenderState(stencilEnabled, true)); + classificationPrimitive._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(stencilEnabled, false)); + classificationPrimitive._rsStencilDepthPass3DTiles = RenderState.fromCache(getStencilDepthRenderState(stencilEnabled, true)); + classificationPrimitive._rsColorPass = RenderState.fromCache(getColorRenderState(stencilEnabled, false)); classificationPrimitive._rsPickPass = RenderState.fromCache(pickRenderState); } @@ -676,6 +682,7 @@ define([ var i; var command; + var derivedCommand; var vaIndex = 0; var uniformMap = primitive._batchTable.getUniformMapCallback()(classificationPrimitive._uniformMap); @@ -684,7 +691,7 @@ define([ for (i = 0; i < length; i += 3) { var vertexArray = primitive._va[vaIndex++]; - // stencil preload command + // Stencil preload command command = colorCommands[i]; if (!defined(command)) { command = colorCommands[i] = new DrawCommand({ @@ -697,8 +704,14 @@ define([ command.renderState = classificationPrimitive._rsStencilPreloadPass; command.shaderProgram = classificationPrimitive._sp; command.uniformMap = uniformMap; + command.pass = Pass.TERRAIN_CLASSIFICATION; - // stencil depth command + derivedCommand = DrawCommand.shallowClone(command, command.derivedCommands.tileset); + derivedCommand.renderState = classificationPrimitive._rsStencilPreloadPass3DTiles; + derivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; + command.derivedCommands.tileset = derivedCommand; + + // Stencil depth command command = colorCommands[i + 1]; if (!defined(command)) { command = colorCommands[i + 1] = new DrawCommand({ @@ -711,8 +724,14 @@ define([ command.renderState = classificationPrimitive._rsStencilDepthPass; command.shaderProgram = classificationPrimitive._sp; command.uniformMap = uniformMap; + command.pass = Pass.TERRAIN_CLASSIFICATION; + + derivedCommand = DrawCommand.shallowClone(command, command.derivedCommands.tileset); + derivedCommand.renderState = classificationPrimitive._rsStencilDepthPass3DTiles; + derivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; + command.derivedCommands.tileset = derivedCommand; - // color command + // Color command command = colorCommands[i + 2]; if (!defined(command)) { command = colorCommands[i + 2] = new DrawCommand({ @@ -724,6 +743,7 @@ define([ command.vertexArray = vertexArray; command.renderState = classificationPrimitive._rsColorPass; command.shaderProgram = classificationPrimitive._spColor; + command.pass = Pass.TERRAIN_CLASSIFICATION; var appearance = classificationPrimitive.appearance; var material = appearance.material; @@ -733,17 +753,22 @@ define([ command.uniformMap = uniformMap; - // derive for 2D if texture coordinates are ever computed + derivedCommand = DrawCommand.shallowClone(command, command.derivedCommands.tileset); + derivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; + command.derivedCommands.tileset = derivedCommand; + + // Derive for 2D if texture coordinates are ever computed if (needs2DShader) { - var derivedColorCommand = command.derivedCommands.appearance2D; - if (!defined(derivedColorCommand)) { - derivedColorCommand = DrawCommand.shallowClone(command); - command.derivedCommands.appearance2D = derivedColorCommand; - } - derivedColorCommand.vertexArray = vertexArray; - derivedColorCommand.renderState = classificationPrimitive._rsColorPass; - derivedColorCommand.shaderProgram = classificationPrimitive._spColor2D; - derivedColorCommand.uniformMap = uniformMap; + // First derive from the terrain command + var derived2DCommand = DrawCommand.shallowClone(command, command.derivedCommands.appearance2D); + derived2DCommand.shaderProgram = classificationPrimitive._spColor2D; + command.derivedCommands.appearance2D = derived2DCommand; + + // Then derive from the 3D Tiles command + derived2DCommand = DrawCommand.shallowClone(derivedCommand, derivedCommand.derivedCommands.appearance2D); + derived2DCommand.shaderProgram = classificationPrimitive._spColor2D; + derived2DCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; + derivedCommand.derivedCommands.appearance2D = derived2DCommand; } } @@ -785,6 +810,7 @@ define([ var j; var command; + var derivedCommand; var vaIndex = 0; var uniformMap = primitive._batchTable.getUniformMapCallback()(classificationPrimitive._uniformMap); @@ -797,7 +823,7 @@ define([ vertexArray = primitive._va[pickOffset.index]; } - // stencil preload command + // Stencil preload command command = pickCommands[j]; if (!defined(command)) { command = pickCommands[j] = new DrawCommand({ @@ -811,12 +837,19 @@ define([ command.renderState = classificationPrimitive._rsStencilPreloadPass; command.shaderProgram = classificationPrimitive._sp; command.uniformMap = uniformMap; + command.pass = Pass.TERRAIN_CLASSIFICATION; if (usePickOffsets) { command.offset = pickOffset.offset; command.count = pickOffset.count; } - // stencil depth command + // Derive for 3D Tiles classification + derivedCommand = DrawCommand.shallowClone(command, command.derivedCommands.tileset); + derivedCommand.renderState = classificationPrimitive._rsStencilPreloadPass3DTiles; + derivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; + command.derivedCommands.tileset = derivedCommand; + + // Stencil depth command command = pickCommands[j + 1]; if (!defined(command)) { command = pickCommands[j + 1] = new DrawCommand({ @@ -830,12 +863,19 @@ define([ command.renderState = classificationPrimitive._rsStencilDepthPass; command.shaderProgram = classificationPrimitive._sp; command.uniformMap = uniformMap; + command.pass = Pass.TERRAIN_CLASSIFICATION; if (usePickOffsets) { command.offset = pickOffset.offset; command.count = pickOffset.count; } - // pick color command + // Derive for 3D Tiles classification + derivedCommand = DrawCommand.shallowClone(command, command.derivedCommands.tileset); + derivedCommand.renderState = classificationPrimitive._rsStencilDepthPass3DTiles; + derivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; + command.derivedCommands.tileset = derivedCommand; + + // Pick color command command = pickCommands[j + 2]; if (!defined(command)) { command = pickCommands[j + 2] = new DrawCommand({ @@ -849,22 +889,28 @@ define([ command.renderState = classificationPrimitive._rsPickPass; command.shaderProgram = classificationPrimitive._spPick; command.uniformMap = uniformMap; + command.pass = Pass.TERRAIN_CLASSIFICATION; if (usePickOffsets) { command.offset = pickOffset.offset; command.count = pickOffset.count; } - // derive for 2D if texture coordinates are ever computed + derivedCommand = DrawCommand.shallowClone(command, command.derivedCommands.tileset); + derivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; + command.derivedCommands.tileset = derivedCommand; + + // Derive for 2D if texture coordinates are ever computed if (needs2DShader) { - var derivedPickCommand = command.derivedCommands.pick2D; - if (!defined(derivedPickCommand)) { - derivedPickCommand = DrawCommand.shallowClone(command); - command.derivedCommands.pick2D = derivedPickCommand; - } - derivedPickCommand.vertexArray = vertexArray; - derivedPickCommand.renderState = classificationPrimitive._rsPickPass; - derivedPickCommand.shaderProgram = classificationPrimitive._spPick2D; - derivedPickCommand.uniformMap = uniformMap; + // First derive from the terrain command + var derived2DCommand = DrawCommand.shallowClone(command, command.derivedCommands.pick2D); + derived2DCommand.shaderProgram = classificationPrimitive._spPick2D; + command.derivedCommands.pick2D = derived2DCommand; + + // Then derive from the 3D Tiles command + derived2DCommand = DrawCommand.shallowClone(derivedCommand, derivedCommand.derivedCommands.pick2D); + derived2DCommand.shaderProgram = classificationPrimitive._spPick2D; + derived2DCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; + derivedCommand.derivedCommands.pick2D = derived2DCommand; } } } @@ -878,6 +924,23 @@ define([ return Math.floor((commandIndex % length) / 3); } + function updateAndQueueRenderCommand(command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume) { + command.modelMatrix = modelMatrix; + command.boundingVolume = boundingVolume; + command.cull = cull; + command.debugShowBoundingVolume = debugShowBoundingVolume; + + frameState.commandList.push(command); + } + + function updateAndQueuePickCommand(command, frameState, modelMatrix, cull, boundingVolume) { + command.modelMatrix = modelMatrix; + command.boundingVolume = boundingVolume; + command.cull = cull; + + frameState.commandList.push(command); + } + function updateAndQueueCommands(classificationPrimitive, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume, twoPasses) { var primitive = classificationPrimitive._primitive; Primitive._updateBoundingVolumes(primitive, frameState, modelMatrix); @@ -893,49 +956,37 @@ define([ boundingVolumes = primitive._boundingSphereMorph; } - var commandList = frameState.commandList; + var classificationType = classificationPrimitive.classificationType; + var queueTerrainCommands = (classificationType !== ClassificationType.CESIUM_3D_TILE); + var queue3DTilesCommands = (classificationType !== ClassificationType.TERRAIN); + var passes = frameState.passes; var i; - var pass; - switch (classificationPrimitive.classificationType) { - case ClassificationType.TERRAIN: - pass = Pass.TERRAIN_CLASSIFICATION; - break; - case ClassificationType.CESIUM_3D_TILE: - pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; - break; - default: - pass = Pass.CLASSIFICATION; - } + var boundingVolume; + var command; if (passes.render) { - var colorCommand; var colorLength = colorCommands.length; for (i = 0; i < colorLength; ++i) { - colorCommand = colorCommands[i]; - colorCommand.modelMatrix = modelMatrix; - colorCommand.boundingVolume = boundingVolumes[boundingVolumeIndex(i, colorLength)]; - colorCommand.cull = cull; - colorCommand.debugShowBoundingVolume = debugShowBoundingVolume; - colorCommand.pass = pass; - - commandList.push(colorCommand); + boundingVolume = boundingVolumes[boundingVolumeIndex(i, colorLength)]; + if (queueTerrainCommands) { + command = colorCommands[i]; + updateAndQueueRenderCommand(command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume); + } + if (queue3DTilesCommands) { + command = colorCommands[i].derivedCommands.tileset; + updateAndQueueRenderCommand(command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume); + } } if (frameState.invertClassification) { var ignoreShowCommands = classificationPrimitive._commandsIgnoreShow; var ignoreShowCommandsLength = ignoreShowCommands.length; - for (i = 0; i < ignoreShowCommandsLength; ++i) { - var bvIndex = Math.floor(i / 2); - colorCommand = ignoreShowCommands[i]; - colorCommand.modelMatrix = modelMatrix; - colorCommand.boundingVolume = boundingVolumes[bvIndex]; - colorCommand.cull = cull; - colorCommand.debugShowBoundingVolume = debugShowBoundingVolume; - - commandList.push(colorCommand); + boundingVolume = boundingVolumes[Math.floor(i / 2)]; + command = ignoreShowCommands[i]; + updateAndQueueRenderCommand(command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume); } } } @@ -945,13 +996,15 @@ define([ var pickOffsets = primitive._pickOffsets; for (i = 0; i < pickLength; ++i) { var pickOffset = pickOffsets[boundingVolumeIndex(i, pickLength)]; - var pickCommand = pickCommands[i]; - pickCommand.modelMatrix = modelMatrix; - pickCommand.boundingVolume = boundingVolumes[pickOffset.index]; - pickCommand.cull = cull; - pickCommand.pass = pass; - - commandList.push(pickCommand); + boundingVolume = boundingVolumes[pickOffset.index]; + if (queueTerrainCommands) { + command = pickCommands[i]; + updateAndQueuePickCommand(command, frameState, modelMatrix, cull, boundingVolume); + } + if (queue3DTilesCommands) { + command = pickCommands[i].derivedCommands.tileset; + updateAndQueuePickCommand(command, frameState, modelMatrix, cull, boundingVolume); + } } } } @@ -1107,13 +1160,17 @@ define([ if (this.debugShowShadowVolume && !this._debugShowShadowVolume && this._ready) { this._debugShowShadowVolume = true; - this._rsStencilPreloadPass = RenderState.fromCache(getStencilPreloadRenderState(false)); - this._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(false)); + this._rsStencilPreloadPass = RenderState.fromCache(getStencilPreloadRenderState(false, false)); + this._rsStencilPreloadPass3DTiles = RenderState.fromCache(getStencilPreloadRenderState(false, true)); + this._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(false, false)); + this._rsStencilDepthPass3DTiles = RenderState.fromCache(getStencilDepthRenderState(false, true)); this._rsColorPass = RenderState.fromCache(getColorRenderState(false)); } else if (!this.debugShowShadowVolume && this._debugShowShadowVolume) { this._debugShowShadowVolume = false; - this._rsStencilPreloadPass = RenderState.fromCache(getStencilPreloadRenderState(true)); - this._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(true)); + this._rsStencilPreloadPass = RenderState.fromCache(getStencilPreloadRenderState(true, false)); + this._rsStencilPreloadPass3DTiles = RenderState.fromCache(getStencilPreloadRenderState(true, true)); + this._rsStencilDepthPass = RenderState.fromCache(getStencilDepthRenderState(true, false)); + this._rsStencilDepthPass3DTiles = RenderState.fromCache(getStencilDepthRenderState(true, true)); this._rsColorPass = RenderState.fromCache(getColorRenderState(true)); } // Update primitive appearance diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 2df59183af5a..3efbaac2bd55 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -514,6 +514,41 @@ define([ return Math.floor((commandIndex % length) / 3); } + function updateAndQueueRenderCommand(groundPrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume) { + // Use derived appearance command for 2D if needed + var classificationPrimitive = groundPrimitive._primitive; + if (frameState.mode !== SceneMode.SCENE3D && + command.shaderProgram === classificationPrimitive._spColor && + classificationPrimitive._needs2DShader) { + command = command.derivedCommands.appearance2D; + } + + command.owner = groundPrimitive; + command.modelMatrix = modelMatrix; + command.boundingVolume = boundingVolume; + command.cull = cull; + command.debugShowBoundingVolume = debugShowBoundingVolume; + + frameState.commandList.push(command); + } + + function updateAndQueuePickCommand(groundPrimitive, command, frameState, modelMatrix, cull, boundingVolume) { + // Use derived pick command for 2D if needed + var classificationPrimitive = groundPrimitive._primitive; + if (frameState.mode !== SceneMode.SCENE3D && + command.shaderProgram === classificationPrimitive._spPick && + classificationPrimitive._needs2DShader) { + command = command.derivedCommands.pick2D; + } + + command.owner = groundPrimitive; + command.modelMatrix = modelMatrix; + command.boundingVolume = boundingVolume; + command.cull = cull; + + frameState.commandList.push(command); + } + function updateAndQueueCommands(groundPrimitive, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume, twoPasses) { var boundingVolumes; if (frameState.mode === SceneMode.SCENE3D) { @@ -522,59 +557,39 @@ define([ boundingVolumes = groundPrimitive._boundingVolumes2D; } - var pass; - switch (groundPrimitive.classificationType) { - case ClassificationType.TERRAIN: - pass = Pass.TERRAIN_CLASSIFICATION; - break; - case ClassificationType.CESIUM_3D_TILE: - pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; - break; - default: - pass = Pass.CLASSIFICATION; - } + var classificationType = groundPrimitive.classificationType; + var queueTerrainCommands = (classificationType !== ClassificationType.CESIUM_3D_TILE); + var queue3DTilesCommands = (classificationType !== ClassificationType.TERRAIN); - var commandList = frameState.commandList; var passes = frameState.passes; var classificationPrimitive = groundPrimitive._primitive; + + var i; + var boundingVolume; + var command; + if (passes.render) { var colorLength = colorCommands.length; - var i; - var colorCommand; for (i = 0; i < colorLength; ++i) { - colorCommand = colorCommands[i]; - - // Use derived appearance command for 2D if needed - if (frameState.mode !== SceneMode.SCENE3D && - colorCommand.shaderProgram === classificationPrimitive._spColor && - classificationPrimitive._needs2DShader) { - colorCommand = colorCommand.derivedCommands.appearance2D; + boundingVolume = boundingVolumes[boundingVolumeIndex(i, colorLength)]; + if (queueTerrainCommands) { + command = colorCommands[i]; + updateAndQueueRenderCommand(groundPrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume); + } + if (queue3DTilesCommands) { + command = colorCommands[i].derivedCommands.tileset; + updateAndQueueRenderCommand(groundPrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume); } - - colorCommand.owner = groundPrimitive; - colorCommand.modelMatrix = modelMatrix; - colorCommand.boundingVolume = boundingVolumes[boundingVolumeIndex(i, colorLength)]; - colorCommand.cull = cull; - colorCommand.debugShowBoundingVolume = debugShowBoundingVolume; - colorCommand.pass = pass; - - commandList.push(colorCommand); } if (frameState.invertClassification) { var ignoreShowCommands = classificationPrimitive._commandsIgnoreShow; var ignoreShowCommandsLength = ignoreShowCommands.length; - for (i = 0; i < ignoreShowCommandsLength; ++i) { - var bvIndex = Math.floor(i / 2); - colorCommand = ignoreShowCommands[i]; - colorCommand.modelMatrix = modelMatrix; - colorCommand.boundingVolume = boundingVolumes[bvIndex]; - colorCommand.cull = cull; - colorCommand.debugShowBoundingVolume = debugShowBoundingVolume; - - commandList.push(colorCommand); + boundingVolume = boundingVolumes[Math.floor(i / 2)]; + command = ignoreShowCommands[i]; + updateAndQueueRenderCommand(groundPrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume); } } } @@ -585,31 +600,22 @@ define([ var pickOffsets; if (!groundPrimitive._useFragmentCulling) { // Must be using pick offsets - classificationPrimitive = groundPrimitive._primitive; pickOffsets = classificationPrimitive._primitive._pickOffsets; } - for (var j = 0; j < pickLength; ++j) { - var pickCommand = pickCommands[j]; - - // Use derived pick command for 2D if needed - if (frameState.mode !== SceneMode.SCENE3D && - pickCommand.shaderProgram === classificationPrimitive._spPick && - classificationPrimitive._needs2DShader) { - pickCommand = pickCommand.derivedCommands.pick2D; - } - var bv = boundingVolumes[boundingVolumeIndex(j, pickLength)]; + for (i = 0; i < pickLength; ++i) { + boundingVolume = boundingVolumes[boundingVolumeIndex(i, pickLength)]; if (!groundPrimitive._useFragmentCulling) { - var pickOffset = pickOffsets[boundingVolumeIndex(j, pickLength)]; - bv = boundingVolumes[pickOffset.index]; + var pickOffset = pickOffsets[boundingVolumeIndex(i, pickLength)]; + boundingVolume = boundingVolumes[pickOffset.index]; + } + if (queueTerrainCommands) { + command = pickCommands[i]; + updateAndQueuePickCommand(groundPrimitive, command, frameState, modelMatrix, cull, boundingVolume); + } + if (queue3DTilesCommands) { + command = pickCommands[i].derivedCommands.tileset; + updateAndQueuePickCommand(groundPrimitive, command, frameState, modelMatrix, cull, boundingVolume); } - - pickCommand.owner = groundPrimitive; - pickCommand.modelMatrix = modelMatrix; - pickCommand.boundingVolume = bv; - pickCommand.cull = cull; - pickCommand.pass = pass; - - commandList.push(pickCommand); } } } diff --git a/Source/Scene/InvertClassification.js b/Source/Scene/InvertClassification.js index b7b7f66889c9..c468b7c93660 100644 --- a/Source/Scene/InvertClassification.js +++ b/Source/Scene/InvertClassification.js @@ -16,6 +16,7 @@ define([ '../Renderer/TextureWrap', '../Shaders/PostProcessStages/PassThrough', './BlendingState', + './StencilConstants', './StencilFunction', './StencilOperation' ], function( @@ -36,6 +37,7 @@ define([ TextureWrap, PassThrough, BlendingState, + StencilConstants, StencilFunction, StencilOperation) { 'use strict'; @@ -96,12 +98,6 @@ define([ return context.depthTexture && context.fragmentDepth; }; - // The stencil mask only uses the least significant 4 bits. - // This is so 3D Tiles with the skip LOD optimization, which uses the most significant 4 bits, - // can be classified. - var stencilMask = 0x0F; - var stencilReference = 0; - var rsUnclassified = { depthMask : false, stencilTest : { @@ -113,9 +109,10 @@ define([ zPass : StencilOperation.KEEP }, backFunction : StencilFunction.NEVER, - reference : stencilReference, - mask : stencilMask + reference : 0, + mask : StencilConstants.CLASSIFICATION_MASK }, + stencilMask : StencilConstants.CLASSIFICATION_MASK, blending : BlendingState.ALPHA_BLEND }; @@ -130,9 +127,10 @@ define([ zPass : StencilOperation.KEEP }, backFunction : StencilFunction.NEVER, - reference : stencilReference, - mask : stencilMask + reference : 0, + mask : StencilConstants.CLASSIFICATION_MASK }, + stencilMask : StencilConstants.CLASSIFICATION_MASK, blending : BlendingState.ALPHA_BLEND }; diff --git a/Source/Scene/PointCloud.js b/Source/Scene/PointCloud.js index 5bf917a6016c..c297f51138d3 100644 --- a/Source/Scene/PointCloud.js +++ b/Source/Scene/PointCloud.js @@ -739,13 +739,18 @@ define([ attributes : attributes }); - pointCloud._opaqueRenderState = RenderState.fromCache({ + var opaqueRenderState = { depthTest : { enabled : true - }, - stencilTest : StencilConstants.setCesium3DTileBit(), - stencilMask : StencilConstants.CESIUM_3D_TILE_MASK - }); + } + }; + + if (pointCloud._opaquePass === Pass.CESIUM_3D_TILE) { + opaqueRenderState.stencilTest = StencilConstants.setCesium3DTileBit(); + opaqueRenderState.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK; + } + + pointCloud._opaqueRenderState = RenderState.fromCache(opaqueRenderState); pointCloud._translucentRenderState = RenderState.fromCache({ depthTest : { diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index 4741c2d2ca3a..c144bbbd9c08 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -2214,16 +2214,11 @@ define([ executeCommand(commands[j], scene, context, passState); } - // Draw classification marked for both terrain and 3D Tiles classification - us.updatePass(Pass.CLASSIFICATION); - commands = frustumCommands.commands[Pass.CLASSIFICATION]; - length = frustumCommands.indices[Pass.CLASSIFICATION]; - for (j = 0; j < length; ++j) { - executeCommand(commands[j], scene, context, passState); - } - if (clearGlobeDepth) { clearDepth.execute(context, passState); + if (useDepthPlane) { + depthPlane.execute(context, passState); + } } if (!environmentState.useInvertClassification || picking) { @@ -2244,14 +2239,6 @@ define([ for (j = 0; j < length; ++j) { executeCommand(commands[j], scene, context, passState); } - - // Draw classification marked for both terrain and 3D Tiles classification - us.updatePass(Pass.CLASSIFICATION); - commands = frustumCommands.commands[Pass.CLASSIFICATION]; - length = frustumCommands.indices[Pass.CLASSIFICATION]; - for (j = 0; j < length; ++j) { - executeCommand(commands[j], scene, context, passState); - } } else { // When the invert classification color is opaque: // Main FBO (FBO1): Main_Color + Main_DepthStencil @@ -2327,24 +2314,12 @@ define([ for (j = 0; j < length; ++j) { executeCommand(commands[j], scene, context, passState); } - - // Draw style over classification marked for both terrain and 3D Tiles classification - us.updatePass(Pass.CLASSIFICATION); - commands = frustumCommands.commands[Pass.CLASSIFICATION]; - length = frustumCommands.indices[Pass.CLASSIFICATION]; - for (j = 0; j < length; ++j) { - executeCommand(commands[j], scene, context, passState); - } } if (length > 0 && context.stencilBuffer) { clearStencil.execute(context, passState); } - if (clearGlobeDepth && useDepthPlane) { - depthPlane.execute(context, passState); - } - us.updatePass(Pass.OPAQUE); commands = frustumCommands.commands[Pass.OPAQUE]; length = frustumCommands.indices[Pass.OPAQUE]; diff --git a/Source/Scene/StencilConstants.js b/Source/Scene/StencilConstants.js index 15dff3d46ab8..9ad789e88091 100644 --- a/Source/Scene/StencilConstants.js +++ b/Source/Scene/StencilConstants.js @@ -9,6 +9,10 @@ define([ 'use strict'; /** + * The most significant bit is used to identify whether the pixel is 3D Tiles. + * The next three bits store selection depth for the skip LODs optimization. + * The last four bits are for increment/decrement shadow volume operations for classification. + * * @private */ var StencilConstants = { @@ -33,7 +37,7 @@ define([ zFail : StencilOperation.KEEP, zPass : StencilOperation.REPLACE }, - reference : ~0, + reference : StencilConstants.CESIUM_3D_TILE_MASK, mask : StencilConstants.CESIUM_3D_TILE_MASK }; }; diff --git a/Source/Scene/Vector3DTilePrimitive.js b/Source/Scene/Vector3DTilePrimitive.js index 41459814c3a5..d0f147849e64 100644 --- a/Source/Scene/Vector3DTilePrimitive.js +++ b/Source/Scene/Vector3DTilePrimitive.js @@ -24,6 +24,7 @@ define([ './ClassificationType', './DepthFunction', './Expression', + './StencilConstants', './StencilFunction', './StencilOperation', './Vector3DTileBatch' @@ -53,6 +54,7 @@ define([ ClassificationType, DepthFunction, Expression, + StencilConstants, StencilFunction, StencilOperation, Vector3DTileBatch) { @@ -113,7 +115,9 @@ define([ this._vaSwap = undefined; this._rsStencilPreloadPass = undefined; + this._rsStencilPreloadPass3DTiles = undefined; this._rsStencilDepthPass = undefined; + this._rsStencilDepthPass3DTiles = undefined; this._rsColorPass = undefined; this._rsPickPass = undefined; this._rsWireframe = undefined; @@ -365,69 +369,74 @@ define([ }); } - var stencilReference = 0; - var stencilMask = 0x0F; - - var stencilPreloadRenderState = { - colorMask : { - red : false, - green : false, - blue : false, - alpha : false - }, - stencilTest : { - enabled : true, - frontFunction : StencilFunction.ALWAYS, - frontOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.DECREMENT_WRAP, - zPass : StencilOperation.DECREMENT_WRAP + function getStencilPreloadRenderState(mask3DTiles) { + var stencilFunction = mask3DTiles ? StencilFunction.EQUAL : StencilFunction.ALWAYS; + return { + colorMask : { + red : false, + green : false, + blue : false, + alpha : false }, - backFunction : StencilFunction.ALWAYS, - backOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.INCREMENT_WRAP, - zPass : StencilOperation.INCREMENT_WRAP + 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 }, - reference : stencilReference, - mask : stencilMask - }, - depthTest : { - enabled : false - }, - depthMask : false - }; + stencilMask : StencilConstants.CLASSIFICATION_MASK, + depthTest : { + enabled : false + }, + depthMask : false + }; + } - var stencilDepthRenderState = { - colorMask : { - red : false, - green : false, - blue : false, - alpha : false - }, - stencilTest : { - enabled : true, - frontFunction : StencilFunction.ALWAYS, - frontOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.INCREMENT_WRAP + function getStencilDepthRenderState(mask3DTiles) { + var stencilFunction = mask3DTiles ? StencilFunction.EQUAL : StencilFunction.ALWAYS; + return { + colorMask : { + red : false, + green : false, + blue : false, + alpha : false }, - backFunction : StencilFunction.ALWAYS, - backOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.DECREMENT_WRAP + 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 }, - reference : stencilReference, - mask : stencilMask - }, - depthTest : { - enabled : true, - func : DepthFunction.LESS_OR_EQUAL - }, - depthMask : false - }; + stencilMask : StencilConstants.CLASSIFICATION_MASK, + depthTest : { + enabled : true, + func : DepthFunction.LESS_OR_EQUAL + }, + depthMask : false + }; + } var colorRenderState = { stencilTest : { @@ -444,9 +453,10 @@ define([ zFail : StencilOperation.KEEP, zPass : StencilOperation.DECREMENT_WRAP }, - reference : stencilReference, - mask : stencilMask + reference : 0, + mask : StencilConstants.CLASSIFICATION_MASK }, + stencilMask : StencilConstants.CLASSIFICATION_MASK, depthTest : { enabled : false }, @@ -469,9 +479,10 @@ define([ zFail : StencilOperation.KEEP, zPass : StencilOperation.DECREMENT_WRAP }, - reference : stencilReference, - mask : stencilMask + reference : 0, + mask : StencilConstants.CLASSIFICATION_MASK }, + stencilMask : StencilConstants.CLASSIFICATION_MASK, depthTest : { enabled : false }, @@ -483,8 +494,10 @@ define([ return; } - primitive._rsStencilPreloadPass = RenderState.fromCache(stencilPreloadRenderState); - primitive._rsStencilDepthPass = RenderState.fromCache(stencilDepthRenderState); + 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); } @@ -727,6 +740,12 @@ define([ 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)) { @@ -744,6 +763,12 @@ define([ 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)) { @@ -761,6 +786,11 @@ define([ 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; @@ -832,6 +862,12 @@ define([ 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)) { @@ -849,6 +885,12 @@ define([ 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)) { @@ -866,6 +908,11 @@ define([ 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; @@ -1053,14 +1100,26 @@ define([ this._batchDirty = true; }; - function queueCommands(frameState, pass, commands, commandsIgnoreShow) { + 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) { - var command = commands[i]; - command.pass = pass; - commandList.push(command); + 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)) { @@ -1130,18 +1189,6 @@ define([ createRenderStates(this); createUniformMap(this, context); - var pass; - switch (this.classificationType) { - case ClassificationType.TERRAIN: - pass = Pass.TERRAIN_CLASSIFICATION; - break; - case ClassificationType.CESIUM_3D_TILE: - pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; - break; - default: - pass = Pass.CLASSIFICATION; - } - var passes = frameState.passes; if (passes.render) { createColorCommands(this, context); @@ -1151,13 +1198,13 @@ define([ if (this._debugWireframe) { queueWireframeCommands(frameState, this._commands); } else { - queueCommands(frameState, pass, this._commands, this._commandsIgnoreShow); + queueCommands(this, frameState, this._commands, this._commandsIgnoreShow); } } if (passes.pick) { createPickCommands(this); - queueCommands(frameState, pass, this._pickCommands); + queueCommands(this, frameState, this._pickCommands); } }; diff --git a/Source/Shaders/Builtin/Constants/passOpaque.glsl b/Source/Shaders/Builtin/Constants/passOpaque.glsl index 8dfb5126f13a..8465b01838d1 100644 --- a/Source/Shaders/Builtin/Constants/passOpaque.glsl +++ b/Source/Shaders/Builtin/Constants/passOpaque.glsl @@ -6,4 +6,4 @@ * * @see czm_pass */ -const float czm_passOpaque = 8.0; +const float czm_passOpaque = 7.0; diff --git a/Source/Shaders/Builtin/Constants/passOverlay.glsl b/Source/Shaders/Builtin/Constants/passOverlay.glsl index 6aea11eb1ee0..e104cb08dd74 100644 --- a/Source/Shaders/Builtin/Constants/passOverlay.glsl +++ b/Source/Shaders/Builtin/Constants/passOverlay.glsl @@ -6,4 +6,4 @@ * * @see czm_pass */ -const float czm_passOverlay = 10.0; +const float czm_passOverlay = 9.0; diff --git a/Source/Shaders/Builtin/Constants/passTranslucent.glsl b/Source/Shaders/Builtin/Constants/passTranslucent.glsl index 1fd11409cc8b..78cf93eb138f 100644 --- a/Source/Shaders/Builtin/Constants/passTranslucent.glsl +++ b/Source/Shaders/Builtin/Constants/passTranslucent.glsl @@ -6,4 +6,4 @@ * * @see czm_pass */ -const float czm_passTranslucent = 9.0; +const float czm_passTranslucent = 8.0; From 81713267b5720c0563b03a4984a542bc1e564cee Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 17 Dec 2018 13:27:58 -0500 Subject: [PATCH 03/39] Fix vector tile wireframe --- Source/Scene/Vector3DTileContent.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Scene/Vector3DTileContent.js b/Source/Scene/Vector3DTileContent.js index 4db34f4c8e2f..131e04f606a1 100644 --- a/Source/Scene/Vector3DTileContent.js +++ b/Source/Scene/Vector3DTileContent.js @@ -511,6 +511,7 @@ define([ var ready = true; if (defined(this._polygons)) { this._polygons.classificationType = this._tileset.classificationType; + this._polygons.debugWireframe = this._tileset.debugWireframe; this._polygons.update(frameState); ready = ready && this._polygons._ready; } From 056fa6caf7b17060e460c91f77745e792bda098e Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 17 Dec 2018 16:48:47 -0500 Subject: [PATCH 04/39] Tests for Batched3DModel3DTileContentClassificationSpec --- ...d3DModel3DTileContentClassificationSpec.js | 158 +++++++++++++----- 1 file changed, 112 insertions(+), 46 deletions(-) diff --git a/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js b/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js index a9ebbd728136..4323cda58d68 100644 --- a/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js +++ b/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js @@ -13,10 +13,12 @@ defineSuite([ 'Core/RectangleGeometry', 'Core/Transforms', 'Renderer/Pass', + 'Renderer/RenderState', 'Scene/Batched3DModel3DTileContent', 'Scene/ClassificationType', 'Scene/PerInstanceColorAppearance', 'Scene/Primitive', + 'Scene/StencilConstants', 'Specs/Cesium3DTilesTester', 'Specs/createScene' ], 'Scene/Batched3DModel3DTileContentClassification', function( @@ -34,41 +36,78 @@ defineSuite([ RectangleGeometry, Transforms, Pass, + RenderState, Batched3DModel3DTileContent, ClassificationType, PerInstanceColorAppearance, Primitive, + StencilConstants, Cesium3DTilesTester, createScene) { 'use strict'; var scene; + var modelMatrix; var centerLongitude = -1.31968; var centerLatitude = 0.698874; var withBatchTableUrl = './Data/Cesium3DTiles/Batched/BatchedWithBatchTable/tileset.json'; var withBatchTableBinaryUrl = './Data/Cesium3DTiles/Batched/BatchedWithBatchTableBinary/tileset.json'; - function setCamera(longitude, latitude) { + function setCamera(longitude, latitude, offset) { // One feature is located at the center, point the camera there var center = Cartesian3.fromRadians(longitude, latitude); scene.camera.lookAt(center, new HeadingPitchRange(0.0, -1.57, 15.0)); + scene.camera.moveUp(offset); } - beforeAll(function() { - scene = createScene(); - }); + function viewCenter() { + setCamera(centerLongitude, centerLatitude, 0.0); + } - afterAll(function() { - scene.destroyForSpecs(); - }); + function viewGlobePrimitive() { + setCamera(centerLongitude, centerLatitude, 0.5); + } - function MockGlobePrimitive(primitive) { - this._primitive = primitive; - this.pass = Pass.CESIUM_3D_TILE; + function view3DTilesPrimitive() { + setCamera(centerLongitude, centerLatitude, -0.5); } - MockGlobePrimitive.prototype.update = function(frameState) { + function MockPrimitive(rectangle, pass) { + var renderState; + if (pass === Pass.CESIUM_3D_TILE) { + renderState = RenderState.fromCache({ + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK, + depthTest : { + enabled : true + } + }); + } + var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 0.0, 1.0)); + this._primitive = new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new RectangleGeometry({ + ellipsoid : Ellipsoid.WGS84, + rectangle : rectangle + }), + id : 'depth rectangle', + attributes : { + color : depthColorAttribute + } + }), + appearance : new PerInstanceColorAppearance({ + translucent : false, + flat : true, + renderState : renderState + }), + asynchronous : false + }); + + this.pass = pass; + } + + MockPrimitive.prototype.update = function(frameState) { var commandList = frameState.commandList; var startLength = commandList.length; this._primitive.update(frameState); @@ -79,68 +118,95 @@ defineSuite([ } }; - MockGlobePrimitive.prototype.isDestroyed = function() { + MockPrimitive.prototype.isDestroyed = function() { return false; }; - MockGlobePrimitive.prototype.destroy = function() { + MockPrimitive.prototype.destroy = function() { this._primitive.destroy(); return destroyObject(this); }; - beforeEach(function() { - setCamera(centerLongitude, centerLatitude); + beforeAll(function() { + scene = createScene(); + var translation = Ellipsoid.WGS84.geodeticSurfaceNormalCartographic(new Cartographic(centerLongitude, centerLatitude)); + Cartesian3.multiplyByScalar(translation, -5.0, translation); + modelMatrix = Matrix4.fromTranslation(translation); + }); + + afterAll(function() { + scene.destroyForSpecs(); + }); + + beforeEach(function() { var offset = CesiumMath.toRadians(0.01); - var rectangle = new Rectangle(centerLongitude - offset, centerLatitude - offset, centerLongitude + offset, centerLatitude + offset); + var rectangle1 = new Rectangle(centerLongitude - offset, centerLatitude, centerLongitude + offset, centerLatitude + offset); + var rectangle2 = new Rectangle(centerLongitude - offset, centerLatitude - offset, centerLongitude + offset, centerLatitude); - var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 0.0, 1.0)); - var primitive = new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : Ellipsoid.WGS84, - rectangle : rectangle - }), - id : 'depth rectangle', - attributes : { - color : depthColorAttribute - } - }), - appearance : new PerInstanceColorAppearance({ - translucent : false, - flat : true - }), - asynchronous : false - }); + // wrap rectangle primitive so it gets executed during the globe pass or 3D Tiles pass to lay down depth + scene.primitives.add(new MockPrimitive(rectangle1, Pass.GLOBE)); + scene.primitives.add(new MockPrimitive(rectangle2, Pass.CESIUM_3D_TILE)); - // wrap rectangle primitive so it gets executed during the globe pass to lay down depth - scene.primitives.add(new MockGlobePrimitive(primitive)); + viewCenter(); }); afterEach(function() { scene.primitives.removeAll(); }); - it('renders with batch table', function() { - var translation = Ellipsoid.WGS84.geodeticSurfaceNormalCartographic(new Cartographic(centerLongitude, centerLatitude)); - Cartesian3.multiplyByScalar(translation, -5.0, translation); - + it('classifies 3D Tiles', function() { return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl, { classificationType : ClassificationType.CESIUM_3D_TILE, - modelMatrix : Matrix4.fromTranslation(translation) + modelMatrix : modelMatrix }).then(function(tileset) { + view3DTilesPrimitive(); Cesium3DTilesTester.expectRenderTileset(scene, tileset); + viewGlobePrimitive(); + Cesium3DTilesTester.expectRenderBlank(scene, tileset); }); }); - it('renders with binary batch table', function() { - var translation = Ellipsoid.WGS84.geodeticSurfaceNormalCartographic(new Cartographic(centerLongitude, centerLatitude)); - Cartesian3.multiplyByScalar(translation, -5.0, translation); + it('classifies globe', function() { + return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl, { + classificationType : ClassificationType.TERRAIN, + modelMatrix : modelMatrix + }).then(function(tileset) { + view3DTilesPrimitive(); + Cesium3DTilesTester.expectRenderBlank(scene, tileset); + viewGlobePrimitive(); + Cesium3DTilesTester.expectRenderTileset(scene, tileset); + }); + }); + it('classifies both 3D Tiles and globe', function() { + return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl, { + classificationType : ClassificationType.BOTH, + modelMatrix : modelMatrix + }).then(function(tileset) { + view3DTilesPrimitive(); + Cesium3DTilesTester.expectRenderTileset(scene, tileset); + viewGlobePrimitive(); + Cesium3DTilesTester.expectRenderTileset(scene, tileset); + }); + }); + + it('renders with batch table', function() { + return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl, { + classificationType : ClassificationType.BOTH, + modelMatrix : modelMatrix + }).then(function(tileset) { + view3DTilesPrimitive(); + Cesium3DTilesTester.expectRenderTileset(scene, tileset); + }); + }); + + it('renders with binary batch table', function() { return Cesium3DTilesTester.loadTileset(scene, withBatchTableBinaryUrl, { - classificationType : ClassificationType.CESIUM_3D_TILE, - modelMatrix : Matrix4.fromTranslation(translation) + classificationType : ClassificationType.BOTH, + modelMatrix : modelMatrix }).then(function(tileset) { + view3DTilesPrimitive(); Cesium3DTilesTester.expectRenderTileset(scene, tileset); }); }); From 3e8b5789eee1b1240c69f8f60cdc1502a5bbf34a Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 17 Dec 2018 17:16:06 -0500 Subject: [PATCH 05/39] Tests for ClassificationModelSpec --- Specs/Scene/ClassificationModelSpec.js | 223 +++++++++++++++---------- 1 file changed, 138 insertions(+), 85 deletions(-) diff --git a/Specs/Scene/ClassificationModelSpec.js b/Specs/Scene/ClassificationModelSpec.js index f45d4d3fae8e..9fe30b35a07e 100644 --- a/Specs/Scene/ClassificationModelSpec.js +++ b/Specs/Scene/ClassificationModelSpec.js @@ -15,9 +15,11 @@ defineSuite([ 'Core/Resource', 'Core/Transforms', 'Renderer/Pass', + 'Renderer/RenderState', 'Scene/ClassificationType', 'Scene/PerInstanceColorAppearance', 'Scene/Primitive', + 'Scene/StencilConstants', 'Specs/createScene', 'Specs/pollToPromise', 'ThirdParty/GltfPipeline/addDefaults', @@ -40,9 +42,11 @@ defineSuite([ Resource, Transforms, Pass, + RenderState, ClassificationType, PerInstanceColorAppearance, Primitive, + StencilConstants, createScene, pollToPromise, addDefaults, @@ -51,42 +55,67 @@ defineSuite([ 'use strict'; var scene; + var modelMatrix; var centerLongitude = -1.31968; var centerLatitude = 0.698874; var batchedModel = './Data/Models/Classification/batched.glb'; var quantizedModel = './Data/Models/Classification/batchedQuantization.glb'; - function setCamera(longitude, latitude) { + function setCamera(longitude, latitude, offset) { // One feature is located at the center, point the camera there var center = Cartesian3.fromRadians(longitude, latitude); scene.camera.lookAt(center, new HeadingPitchRange(0.0, -1.57, 15.0)); + scene.camera.moveUp(offset); } - function loadModel(model) { - return Resource.fetchArrayBuffer(model).then(function(arrayBuffer) { - var gltf = new Uint8Array(arrayBuffer); - gltf = parseGlb(gltf); - updateVersion(gltf); - addDefaults(gltf); - return gltf; - }); + function viewCenter() { + setCamera(centerLongitude, centerLatitude, 0.0); } - beforeAll(function() { - scene = createScene(); - }); + function viewGlobePrimitive() { + setCamera(centerLongitude, centerLatitude, 0.5); + } - afterAll(function() { - scene.destroyForSpecs(); - }); + function view3DTilesPrimitive() { + setCamera(centerLongitude, centerLatitude, -0.5); + } + + function MockPrimitive(rectangle, pass) { + var renderState; + if (pass === Pass.CESIUM_3D_TILE) { + renderState = RenderState.fromCache({ + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK, + depthTest : { + enabled : true + } + }); + } + var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 0.0, 1.0)); + this._primitive = new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new RectangleGeometry({ + ellipsoid : Ellipsoid.WGS84, + rectangle : rectangle + }), + id : 'depth rectangle', + attributes : { + color : depthColorAttribute + } + }), + appearance : new PerInstanceColorAppearance({ + translucent : false, + flat : true, + renderState : renderState + }), + asynchronous : false + }); - function MockGlobePrimitive(primitive) { - this._primitive = primitive; - this.pass = Pass.CESIUM_3D_TILE; + this.pass = pass; } - MockGlobePrimitive.prototype.update = function(frameState) { + MockPrimitive.prototype.update = function(frameState) { var commandList = frameState.commandList; var startLength = commandList.length; this._primitive.update(frameState); @@ -97,57 +126,75 @@ defineSuite([ } }; - MockGlobePrimitive.prototype.isDestroyed = function() { + MockPrimitive.prototype.isDestroyed = function() { return false; }; - MockGlobePrimitive.prototype.destroy = function() { + MockPrimitive.prototype.destroy = function() { this._primitive.destroy(); return destroyObject(this); }; - beforeEach(function() { - setCamera(centerLongitude, centerLatitude); + beforeAll(function() { + scene = createScene(); + var translation = Ellipsoid.WGS84.geodeticSurfaceNormalCartographic(new Cartographic(centerLongitude, centerLatitude)); + Cartesian3.multiplyByScalar(translation, -5.0, translation); + modelMatrix = Matrix4.fromTranslation(translation); + }); + + afterAll(function() { + scene.destroyForSpecs(); + }); + + beforeEach(function() { var offset = CesiumMath.toRadians(0.01); - var rectangle = new Rectangle(centerLongitude - offset, centerLatitude - offset, centerLongitude + offset, centerLatitude + offset); + var rectangle1 = new Rectangle(centerLongitude - offset, centerLatitude, centerLongitude + offset, centerLatitude + offset); + var rectangle2 = new Rectangle(centerLongitude - offset, centerLatitude - offset, centerLongitude + offset, centerLatitude); - var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 0.0, 1.0)); - var primitive = new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : Ellipsoid.WGS84, - rectangle : rectangle - }), - id : 'depth rectangle', - attributes : { - color : depthColorAttribute - } - }), - appearance : new PerInstanceColorAppearance({ - translucent : false, - flat : true - }), - asynchronous : false - }); + // wrap rectangle primitive so it gets executed during the globe pass or 3D Tiles pass to lay down depth + scene.primitives.add(new MockPrimitive(rectangle1, Pass.GLOBE)); + scene.primitives.add(new MockPrimitive(rectangle2, Pass.CESIUM_3D_TILE)); - // wrap rectangle primitive so it gets executed during the globe pass to lay down depth - scene.primitives.add(new MockGlobePrimitive(primitive)); + viewCenter(); }); afterEach(function() { scene.primitives.removeAll(); }); - it('renders batched model', function() { - var translation = Ellipsoid.WGS84.geodeticSurfaceNormalCartographic(new Cartographic(centerLongitude, centerLatitude)); - Cartesian3.multiplyByScalar(translation, -5.0, translation); + function expectRender(scene, model) { + model.show = false; + expect(scene).toRender([0, 0, 0, 255]); + model.show = true; + expect(scene).toRenderAndCall(function(rgba) { + expect(rgba).not.toEqual([0, 0, 0, 255]); + }); + } - return Resource.fetchArrayBuffer(batchedModel).then(function(arrayBuffer) { + function expectRenderBlank(scene, model) { + model.show = false; + expect(scene).toRender([0, 0, 0, 255]); + model.show = true; + expect(scene).toRender([0, 0, 0, 255]); + } + + function loadGltf(model) { + return Resource.fetchArrayBuffer(model).then(function(arrayBuffer) { + var gltf = new Uint8Array(arrayBuffer); + gltf = parseGlb(gltf); + updateVersion(gltf); + addDefaults(gltf); + return gltf; + }); + } + + function loadClassificationModel(url, classificationType) { + return Resource.fetchArrayBuffer(url).then(function(arrayBuffer) { var model = scene.primitives.add(new ClassificationModel({ gltf : arrayBuffer, - classificationType : ClassificationType.CESIUM_3D_TILE, - modelMatrix : Matrix4.fromTranslation(translation) + classificationType : classificationType, + modelMatrix : modelMatrix })); var ready = false; @@ -159,48 +206,54 @@ defineSuite([ scene.renderForSpecs(); return ready; }).then(function() { - model.show = false; - expect(scene).toRender([0, 0, 0, 255]); - model.show = true; - expect(scene).toRenderAndCall(function(rgba) { - expect(rgba).not.toEqual([0, 0, 0, 255]); - }); + return model; }); }); + } + + it('classifies 3D Tiles', function() { + return loadClassificationModel(batchedModel, ClassificationType.CESIUM_3D_TILE).then(function(model) { + view3DTilesPrimitive(); + expectRender(scene, model); + viewGlobePrimitive(); + expectRenderBlank(scene, model); + }); }); - it('renders batched model with quantization', function() { - var translation = Ellipsoid.WGS84.geodeticSurfaceNormalCartographic(new Cartographic(centerLongitude, centerLatitude)); - Cartesian3.multiplyByScalar(translation, -5.0, translation); + it('classifies globe', function() { + return loadClassificationModel(batchedModel, ClassificationType.TERRAIN).then(function(model) { + view3DTilesPrimitive(); + expectRenderBlank(scene, model); + viewGlobePrimitive(); + expectRender(scene, model); + }); + }); - return Resource.fetchArrayBuffer(quantizedModel).then(function(arrayBuffer) { - var model = scene.primitives.add(new ClassificationModel({ - gltf : arrayBuffer, - classificationType : ClassificationType.CESIUM_3D_TILE, - modelMatrix : Matrix4.fromTranslation(translation) - })); + it('classifies both 3D Tiles and globe', function() { + return loadClassificationModel(batchedModel, ClassificationType.BOTH).then(function(model) { + view3DTilesPrimitive(); + expectRender(scene, model); + viewGlobePrimitive(); + expectRender(scene, model); + }); + }); - var ready = false; - model.readyPromise.then(function() { - ready = true; - }); + it('renders batched model', function() { + return loadClassificationModel(batchedModel, ClassificationType.BOTH).then(function(model) { + view3DTilesPrimitive(); + expectRender(scene, model); + }); + }); - return pollToPromise(function() { - scene.renderForSpecs(); - return ready; - }).then(function() { - model.show = false; - expect(scene).toRender([0, 0, 0, 255]); - model.show = true; - expect(scene).toRenderAndCall(function(rgba) { - expect(rgba).not.toEqual([0, 0, 0, 255]); - }); - }); + it('renders batched model with quantization', function() { + return loadClassificationModel(quantizedModel, ClassificationType.BOTH).then(function(model) { + view3DTilesPrimitive(); + expectRender(scene, model); }); }); it('throws with invalid number of nodes', function() { - return loadModel(batchedModel).then(function(gltf) { + return loadGltf(batchedModel).then(function(gltf) { gltf.nodes.push({}); expect(function() { return new ClassificationModel({ @@ -211,7 +264,7 @@ defineSuite([ }); it('throws with invalid number of meshes', function() { - return loadModel(batchedModel).then(function(gltf) { + return loadGltf(batchedModel).then(function(gltf) { gltf.meshes.push({}); expect(function() { return new ClassificationModel({ @@ -222,7 +275,7 @@ defineSuite([ }); it('throws with invalid number of primitives', function() { - return loadModel(batchedModel).then(function(gltf) { + return loadGltf(batchedModel).then(function(gltf) { gltf.meshes[0].primitives.push({}); expect(function() { return new ClassificationModel({ @@ -233,7 +286,7 @@ defineSuite([ }); it('throws with position semantic', function() { - return loadModel(batchedModel).then(function(gltf) { + return loadGltf(batchedModel).then(function(gltf) { gltf.meshes[0].primitives[0].attributes.POSITION = undefined; expect(function() { return new ClassificationModel({ @@ -244,7 +297,7 @@ defineSuite([ }); it('throws with batch id semantic', function() { - return loadModel(batchedModel).then(function(gltf) { + return loadGltf(batchedModel).then(function(gltf) { gltf.meshes[0].primitives[0].attributes._BATCHID = undefined; expect(function() { return new ClassificationModel({ From effcecdc4b6aeb2ae672b0c64c8190402aecd168 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 17 Dec 2018 19:00:39 -0500 Subject: [PATCH 06/39] ClassificationPrimitive and GlobePrimitive tests --- Source/Scene/InvertClassification.js | 7 +- Source/Scene/Scene.js | 13 +- ...d3DModel3DTileContentClassificationSpec.js | 4 +- Specs/Scene/ClassificationPrimitiveSpec.js | 186 +++++++++----- Specs/Scene/GroundPrimitiveSpec.js | 229 +++++++++++------- 5 files changed, 294 insertions(+), 145 deletions(-) diff --git a/Source/Scene/InvertClassification.js b/Source/Scene/InvertClassification.js index c468b7c93660..25b4dff62510 100644 --- a/Source/Scene/InvertClassification.js +++ b/Source/Scene/InvertClassification.js @@ -112,7 +112,6 @@ define([ reference : 0, mask : StencilConstants.CLASSIFICATION_MASK }, - stencilMask : StencilConstants.CLASSIFICATION_MASK, blending : BlendingState.ALPHA_BLEND }; @@ -130,15 +129,19 @@ define([ reference : 0, mask : StencilConstants.CLASSIFICATION_MASK }, - stencilMask : StencilConstants.CLASSIFICATION_MASK, blending : BlendingState.ALPHA_BLEND }; + // Set the 3D Tiles bit when rendering back into the scene's framebuffer. This is only needed if + // invert classification does not use the scene's depth-stencil texture, which is the case if the invert + // classification color is translucent. var rsDefault = { depthMask : true, depthTest : { enabled : true }, + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK, blending : BlendingState.ALPHA_BLEND }; diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index c144bbbd9c08..92823beab81b 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -46,6 +46,7 @@ define([ '../Renderer/Framebuffer', '../Renderer/Pass', '../Renderer/PixelDatatype', + '../Renderer/RenderState', '../Renderer/ShaderProgram', '../Renderer/ShaderSource', '../Renderer/Texture', @@ -76,6 +77,7 @@ define([ './SceneTransitioner', './ScreenSpaceCameraController', './ShadowMap', + './StencilConstants', './SunPostProcess', './TweenCollection', './View' @@ -127,6 +129,7 @@ define([ Framebuffer, Pass, PixelDatatype, + RenderState, ShaderProgram, ShaderSource, Texture, @@ -157,6 +160,7 @@ define([ SceneTransitioner, ScreenSpaceCameraController, ShadowMap, + StencilConstants, SunPostProcess, TweenCollection, View) { @@ -322,6 +326,12 @@ define([ this._stencilClearCommand = new ClearCommand({ stencil : 0 }); + this._classificationStencilClearCommand = new ClearCommand({ + stencil : 0, + renderState : RenderState.fromCache({ + stencilMask : StencilConstants.CLASSIFICATION_MASK + }) + }); this._depthOnlyRenderStateCache = {}; this._pickRenderStateCache = {}; @@ -2146,6 +2156,7 @@ define([ var useDepthPlane = environmentState.useDepthPlane; var clearDepth = scene._depthClearCommand; var clearStencil = scene._stencilClearCommand; + var clearClassificationStencil = scene._classificationStencilClearCommand; var depthPlane = scene._depthPlane; var usePostProcessSelected = environmentState.usePostProcessSelected; @@ -2304,7 +2315,7 @@ define([ // Clear stencil set by the classification for the next classification pass if (length > 0 && context.stencilBuffer) { - clearStencil.execute(context, passState); + clearClassificationStencil.execute(context, passState); } // Draw style over classification. diff --git a/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js b/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js index 4323cda58d68..5242838719b5 100644 --- a/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js +++ b/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js @@ -104,7 +104,7 @@ defineSuite([ asynchronous : false }); - this.pass = pass; + this._pass = pass; } MockPrimitive.prototype.update = function(frameState) { @@ -114,7 +114,7 @@ defineSuite([ for (var i = startLength; i < commandList.length; ++i) { var command = commandList[i]; - command.pass = this.pass; + command.pass = this._pass; } }; diff --git a/Specs/Scene/ClassificationPrimitiveSpec.js b/Specs/Scene/ClassificationPrimitiveSpec.js index e3c278aa3470..d1afb517bcea 100644 --- a/Specs/Scene/ClassificationPrimitiveSpec.js +++ b/Specs/Scene/ClassificationPrimitiveSpec.js @@ -13,11 +13,14 @@ defineSuite([ 'Core/ShowGeometryInstanceAttribute', 'Core/Transforms', 'Renderer/Pass', + 'Renderer/RenderState', + 'Scene/ClassificationType', 'Scene/InvertClassification', 'Scene/MaterialAppearance', 'Scene/PerInstanceColorAppearance', 'Scene/Primitive', 'Scene/ShadowVolumeAppearance', + 'Scene/StencilConstants', 'Specs/createScene', 'Specs/pollToPromise' ], function( @@ -35,11 +38,14 @@ defineSuite([ ShowGeometryInstanceAttribute, Transforms, Pass, + RenderState, + ClassificationType, InvertClassification, MaterialAppearance, PerInstanceColorAppearance, Primitive, ShadowVolumeAppearance, + StencilConstants, createScene, pollToPromise) { 'use strict'; @@ -54,72 +60,97 @@ defineSuite([ var boxInstance; var primitive; - var depthPrimitive; - - beforeAll(function() { - scene = createScene(); - scene.postProcessStages.fxaa.enabled = false; - - ellipsoid = Ellipsoid.WGS84; - }); - - afterAll(function() { - scene.destroyForSpecs(); - }); + var globePrimitive; + var tilesetPrimitive; + var reusableGlobePrimitive; + var reusableTilesetPrimitive; + + function createPrimitive(rectangle, pass) { + var renderState; + if (pass === Pass.CESIUM_3D_TILE) { + renderState = RenderState.fromCache({ + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK, + depthTest : { + enabled : true + } + }); + } + var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 1.0, 1.0)); + depthColor = depthColorAttribute.value; + return new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new RectangleGeometry({ + ellipsoid : Ellipsoid.WGS84, + rectangle : rectangle + }), + id : 'depth rectangle', + attributes : { + color : depthColorAttribute + } + }), + appearance : new PerInstanceColorAppearance({ + translucent : false, + flat : true, + renderState : renderState + }), + asynchronous : false + }); + } - function MockGlobePrimitive(primitive) { + function MockPrimitive(primitive, pass) { this._primitive = primitive; - this.pass = Pass.GLOBE; + this._pass = pass; + this.show = true; } - MockGlobePrimitive.prototype.update = function(frameState) { + MockPrimitive.prototype.update = function(frameState) { + if (!this.show) { + return; + } + var commandList = frameState.commandList; var startLength = commandList.length; this._primitive.update(frameState); for (var i = startLength; i < commandList.length; ++i) { var command = commandList[i]; - command.pass = this.pass; + command.pass = this._pass; } }; - MockGlobePrimitive.prototype.isDestroyed = function() { + MockPrimitive.prototype.isDestroyed = function() { return false; }; - MockGlobePrimitive.prototype.destroy = function() { - this._primitive.destroy(); + MockPrimitive.prototype.destroy = function() { return destroyObject(this); }; - beforeEach(function() { - scene.morphTo3D(0); - scene.render(); // clear any afterRender commands + beforeAll(function() { + scene = createScene(); + scene.postProcessStages.fxaa.enabled = false; + + ellipsoid = Ellipsoid.WGS84; rectangle = Rectangle.fromDegrees(-75.0, 25.0, -70.0, 30.0); + reusableGlobePrimitive = createPrimitive(rectangle, Pass.GLOBE); + reusableTilesetPrimitive = createPrimitive(rectangle, Pass.CESIUM_3D_TILE); + }); - var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 1.0, 1.0)); - depthColor = depthColorAttribute.value; - var primitive = new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : rectangle - }), - id : 'depth rectangle', - attributes : { - color : depthColorAttribute - } - }), - appearance : new PerInstanceColorAppearance({ - translucent : false, - flat : true - }), - asynchronous : false - }); + afterAll(function() { + reusableGlobePrimitive.destroy(); + reusableTilesetPrimitive.destroy(); + scene.destroyForSpecs(); + }); + + beforeEach(function() { + scene.morphTo3D(0); + scene.render(); // clear any afterRender commands - // wrap rectangle primitive so it gets executed during the globe pass to lay down depth - depthPrimitive = new MockGlobePrimitive(primitive); + // wrap rectangle primitive so it gets executed during the globe pass and 3D Tiles pass to lay down depth + globePrimitive = new MockPrimitive(reusableGlobePrimitive, Pass.GLOBE); + tilesetPrimitive = new MockPrimitive(reusableTilesetPrimitive, Pass.CESIUM_3D_TILE); var center = Rectangle.center(rectangle); var origin = ellipsoid.cartographicToCartesian(center); @@ -142,9 +173,11 @@ defineSuite([ }); afterEach(function() { + scene.primitives.removeAll(); scene.groundPrimitives.removeAll(); primitive = primitive && !primitive.isDestroyed() && primitive.destroy(); - depthPrimitive = depthPrimitive && !depthPrimitive.isDestroyed() && depthPrimitive.destroy(); + globePrimitive = globePrimitive && !globePrimitive.isDestroyed() && globePrimitive.destroy(); + tilesetPrimitive = tilesetPrimitive && !tilesetPrimitive.isDestroyed() && tilesetPrimitive.destroy(); }); it('default constructs', function() { @@ -328,17 +361,53 @@ defineSuite([ expect(frameState.commandList.length).toEqual(0); }); - function verifyClassificationPrimitiveRender(primitive, color) { - scene.camera.setView({ destination : rectangle }); + function expectRender(color) { + expect(scene).toRender(color); + } - scene.groundPrimitives.add(depthPrimitive); + function expectRenderBlank() { expect(scene).toRenderAndCall(function(rgba) { expect(rgba).not.toEqual([0, 0, 0, 255]); expect(rgba[0]).toEqual(0); }); + } + + function verifyClassificationPrimitiveRender(primitive, color) { + scene.camera.setView({ destination : rectangle }); + + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); + + expectRenderBlank(); scene.groundPrimitives.add(primitive); - expect(scene).toRender(color); + + primitive.classificationType = ClassificationType.BOTH; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expectRender(color); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expectRender(color); + + primitive.classificationType = ClassificationType.CESIUM_3D_TILE; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expectRender(color); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expectRenderBlank(); + + primitive.classificationType = ClassificationType.TERRAIN; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expectRenderBlank(); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expectRender(color); + + globePrimitive.show = true; + tilesetPrimitive.show = true; } it('renders in 3D', function() { @@ -450,7 +519,6 @@ defineSuite([ scene.invertClassification = true; scene.invertClassificationColor = new Color(0.25, 0.25, 0.25, 1.0); - depthPrimitive.pass = Pass.CESIUM_3D_TILE; boxInstance.attributes.show = new ShowGeometryInstanceAttribute(true); primitive = new ClassificationPrimitive({ @@ -466,7 +534,7 @@ defineSuite([ invertedColor[2] = Color.floatToByte(Color.byteToFloat(depthColor[2]) * scene.invertClassificationColor.blue); invertedColor[3] = 255; - scene.groundPrimitives.add(depthPrimitive); + scene.primitives.add(tilesetPrimitive); expect(scene).toRender(invertedColor); scene.groundPrimitives.add(primitive); @@ -490,7 +558,6 @@ defineSuite([ scene.invertClassification = true; scene.invertClassificationColor = new Color(0.25, 0.25, 0.25, 0.25); - depthPrimitive.pass = Pass.CESIUM_3D_TILE; boxInstance.attributes.show = new ShowGeometryInstanceAttribute(true); primitive = new ClassificationPrimitive({ @@ -506,7 +573,7 @@ defineSuite([ invertedColor[2] = Color.floatToByte(Color.byteToFloat(depthColor[2]) * scene.invertClassificationColor.blue * scene.invertClassificationColor.alpha); invertedColor[3] = 255; - scene.groundPrimitives.add(depthPrimitive); + scene.primitives.add(tilesetPrimitive); expect(scene).toRender(invertedColor); scene.groundPrimitives.add(primitive); @@ -588,6 +655,10 @@ defineSuite([ verifyClassificationPrimitiveRender(primitive, boxColor); + scene.primitives.destroyPrimitives = false; + scene.primitives.removeAll(); + scene.primitives.destroyPrimitives = true; + scene.groundPrimitives.destroyPrimitives = false; scene.groundPrimitives.removeAll(); scene.groundPrimitives.destroyPrimitives = true; @@ -614,6 +685,10 @@ defineSuite([ verifyClassificationPrimitiveRender(primitive, boxColor); + scene.primitives.destroyPrimitives = false; + scene.primitives.removeAll(); + scene.primitives.destroyPrimitives = true; + scene.groundPrimitives.destroyPrimitives = false; scene.groundPrimitives.removeAll(); scene.groundPrimitives.destroyPrimitives = true; @@ -688,9 +763,10 @@ defineSuite([ verifyClassificationPrimitiveRender(primitive, boxColor); expect(scene).toDrillPickAndCall(function(pickedObjects) { - expect(pickedObjects.length).toEqual(2); + expect(pickedObjects.length).toEqual(3); expect(pickedObjects[0].primitive).toEqual(primitive); - expect(pickedObjects[1].primitive).toEqual(depthPrimitive._primitive); + expect(pickedObjects[1].primitive).toEqual(globePrimitive._primitive); + expect(pickedObjects[2].primitive).toEqual(tilesetPrimitive._primitive); }); }); @@ -970,7 +1046,7 @@ defineSuite([ }); scene.camera.setView({ destination : rectangle }); - scene.groundPrimitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); expect(scene).toRenderAndCall(function(rgba) { expect(rgba).not.toEqual([0, 0, 0, 255]); expect(rgba[0]).toEqual(0); diff --git a/Specs/Scene/GroundPrimitiveSpec.js b/Specs/Scene/GroundPrimitiveSpec.js index 9b6b81543666..65e592793db1 100644 --- a/Specs/Scene/GroundPrimitiveSpec.js +++ b/Specs/Scene/GroundPrimitiveSpec.js @@ -15,12 +15,14 @@ defineSuite([ 'Core/RectangleGeometry', 'Core/ShowGeometryInstanceAttribute', 'Renderer/Pass', + 'Renderer/RenderState', 'Scene/ClassificationType', 'Scene/EllipsoidSurfaceAppearance', 'Scene/InvertClassification', 'Scene/Material', 'Scene/PerInstanceColorAppearance', 'Scene/Primitive', + 'Scene/StencilConstants', 'Specs/createCanvas', 'Specs/createScene', 'Specs/pollToPromise' @@ -41,12 +43,14 @@ defineSuite([ RectangleGeometry, ShowGeometryInstanceAttribute, Pass, + RenderState, ClassificationType, EllipsoidSurfaceAppearance, InvertClassification, Material, PerInstanceColorAppearance, Primitive, + StencilConstants, createCanvas, createScene, pollToPromise) { @@ -63,82 +67,108 @@ defineSuite([ var rectangleInstance; var primitive; - var depthPrimitive; - var reusablePrimitive; - - beforeAll(function() { - scene = createScene(); - - scene.postProcessStages.fxaa.enabled = false; - - context = scene.context; - - ellipsoid = Ellipsoid.WGS84; - return GroundPrimitive.initializeTerrainHeights().then(function(){ - var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 1.0, 1.0)); - depthColor = depthColorAttribute.value; - var bigRectangle = Rectangle.fromDegrees(-180 + CesiumMath.EPSILON4, -90 + CesiumMath.EPSILON4, 180 - CesiumMath.EPSILON4, 90 - CesiumMath.EPSILON4); - - reusablePrimitive = new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : bigRectangle - }), - id : 'depth rectangle', - attributes : { - color : depthColorAttribute - } - }), - appearance : new PerInstanceColorAppearance({ - translucent : false, - flat : true - }), - asynchronous : false + var globePrimitive; + var tilesetPrimitive; + var reusableGlobePrimitive; + var reusableTilesetPrimitive; + + function createPrimitive(rectangle, pass) { + var renderState; + if (pass === Pass.CESIUM_3D_TILE) { + renderState = RenderState.fromCache({ + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK, + depthTest : { + enabled : true + } }); + } + var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 1.0, 1.0)); + depthColor = depthColorAttribute.value; + return new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new RectangleGeometry({ + ellipsoid : Ellipsoid.WGS84, + rectangle : rectangle + }), + id : 'depth rectangle', + attributes : { + color : depthColorAttribute + } + }), + appearance : new PerInstanceColorAppearance({ + translucent : false, + flat : true, + renderState : renderState + }), + asynchronous : false }); - }); - - afterAll(function() { - reusablePrimitive.destroy(); - scene.destroyForSpecs(); - // Leave ground primitive uninitialized - ApproximateTerrainHeights._initPromise = undefined; - ApproximateTerrainHeights._terrainHeights = undefined; - }); + } - function MockGlobePrimitive(primitive) { + function MockPrimitive(primitive, pass) { this._primitive = primitive; - this.pass = Pass.GLOBE; + this._pass = pass; + this.show = true; } - MockGlobePrimitive.prototype.update = function(frameState) { + MockPrimitive.prototype.update = function(frameState) { + if (!this.show) { + return; + } + var commandList = frameState.commandList; var startLength = commandList.length; this._primitive.update(frameState); for (var i = startLength; i < commandList.length; ++i) { var command = commandList[i]; - command.pass = this.pass; + command.pass = this._pass; } }; - MockGlobePrimitive.prototype.isDestroyed = function() { + MockPrimitive.prototype.isDestroyed = function() { return false; }; - MockGlobePrimitive.prototype.destroy = function() { + MockPrimitive.prototype.destroy = function() { return destroyObject(this); }; + beforeAll(function() { + scene = createScene(); + + scene.postProcessStages.fxaa.enabled = false; + + context = scene.context; + + ellipsoid = Ellipsoid.WGS84; + + var bigRectangle = Rectangle.fromDegrees(-180 + CesiumMath.EPSILON4, -90 + CesiumMath.EPSILON4, 180 - CesiumMath.EPSILON4, 90 - CesiumMath.EPSILON4); + reusableGlobePrimitive = createPrimitive(bigRectangle, Pass.GLOBE); + reusableTilesetPrimitive = createPrimitive(bigRectangle, Pass.CESIUM_3D_TILE); + + return GroundPrimitive.initializeTerrainHeights(); + + }); + + afterAll(function() { + reusableGlobePrimitive.destroy(); + reusableTilesetPrimitive.destroy(); + scene.destroyForSpecs(); + // Leave ground primitive uninitialized + ApproximateTerrainHeights._initPromise = undefined; + ApproximateTerrainHeights._terrainHeights = undefined; + }); + beforeEach(function() { scene.morphTo3D(0); scene.render(); // clear any afterRender commands rectangle = Rectangle.fromDegrees(-80.0, 20.0, -70.0, 30.0); - // wrap rectangle primitive so it gets executed during the globe pass to lay down depth - depthPrimitive = new MockGlobePrimitive(reusablePrimitive); + // wrap rectangle primitive so it gets executed during the globe pass and 3D Tiles pass to lay down depth + globePrimitive = new MockPrimitive(reusableGlobePrimitive, Pass.GLOBE); + tilesetPrimitive = new MockPrimitive(reusableTilesetPrimitive, Pass.CESIUM_3D_TILE); var rectColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 1.0, 0.0, 1.0)); rectColor = rectColorAttribute.value; @@ -155,9 +185,11 @@ defineSuite([ }); afterEach(function() { + scene.primitives.removeAll(); scene.groundPrimitives.removeAll(); primitive = primitive && !primitive.isDestroyed() && primitive.destroy(); - depthPrimitive = depthPrimitive && !depthPrimitive.isDestroyed() && depthPrimitive.destroy(); + globePrimitive = globePrimitive && !globePrimitive.isDestroyed() && globePrimitive.destroy(); + tilesetPrimitive = tilesetPrimitive && !tilesetPrimitive.isDestroyed() && tilesetPrimitive.destroy(); }); it('default constructs', function() { @@ -342,17 +374,53 @@ defineSuite([ expect(frameState.commandList.length).toEqual(0); }); - function verifyGroundPrimitiveRender(primitive, color) { - scene.camera.setView({ destination : rectangle }); + function expectRender(color) { + expect(scene).toRender(color); + } - scene.groundPrimitives.add(depthPrimitive); + function expectRenderBlank() { expect(scene).toRenderAndCall(function(rgba) { expect(rgba).not.toEqual([0, 0, 0, 255]); expect(rgba[0]).toEqual(0); }); + } + + function verifyGroundPrimitiveRender(primitive, color) { + scene.camera.setView({ destination : rectangle }); + + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); + + expectRenderBlank(); scene.groundPrimitives.add(primitive); - expect(scene).toRender(color); + + primitive.classificationType = ClassificationType.BOTH; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expectRender(color); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expectRender(color); + + primitive.classificationType = ClassificationType.CESIUM_3D_TILE; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expectRender(color); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expectRenderBlank(); + + primitive.classificationType = ClassificationType.TERRAIN; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expectRenderBlank(); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expectRender(color); + + globePrimitive.show = true; + tilesetPrimitive.show = true; } it('renders in 3D', function() { @@ -393,7 +461,7 @@ defineSuite([ scene.camera.setView({ destination : bigIdlRectangle }); - scene.groundPrimitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); expect(scene).toRenderAndCall(function(rgba) { expect(rgba).not.toEqual([0, 0, 0, 255]); expect(rgba[0]).toEqual(0); @@ -428,7 +496,7 @@ defineSuite([ scene.camera.setView({ destination : smallIdlRectangle }); - scene.groundPrimitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); expect(scene).toRenderAndCall(function(rgba) { expect(rgba).not.toEqual([0, 0, 0, 255]); expect(rgba[0]).toEqual(0); @@ -469,39 +537,24 @@ defineSuite([ describe('larger scene', function() { // Screen space techniques may produce unexpected results with 1x1 canvasses var largeScene; - var largeSceneReusablePrimitive; + var largeSceneReusableGlobePrimitive; + var largeSceneReusableTilesetPrimitive; beforeAll(function() { largeScene = createScene({ canvas : createCanvas(2, 2) }); - var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 1.0, 1.0)); - depthColor = depthColorAttribute.value; var bigRectangle = Rectangle.fromDegrees(-180 + CesiumMath.EPSILON4, -90 + CesiumMath.EPSILON4, 180 - CesiumMath.EPSILON4, 90 - CesiumMath.EPSILON4); - - largeSceneReusablePrimitive = new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : bigRectangle - }), - id : 'depth rectangle', - attributes : { - color : depthColorAttribute - } - }), - appearance : new PerInstanceColorAppearance({ - translucent : false, - flat : true - }), - asynchronous : false - }); + largeSceneReusableGlobePrimitive = createPrimitive(bigRectangle, Pass.GLOBE); + largeSceneReusableTilesetPrimitive = createPrimitive(bigRectangle, Pass.CESIUM_3D_TILE); }); afterAll(function() { - largeSceneReusablePrimitive.destroy(); + largeSceneReusableGlobePrimitive.destroy(); + largeSceneReusableTilesetPrimitive.destroy(); largeScene.destroyForSpecs(); }); afterEach(function(){ + largeScene.primitives.removeAll(); largeScene.groundPrimitives.removeAll(); }); @@ -511,9 +564,9 @@ defineSuite([ largeScene.postProcessStages.fxaa.enabled = false; largeScene.camera.setView({destination : destination}); - var largeSceneDepthPrimitive = new MockGlobePrimitive(largeSceneReusablePrimitive); + var largeSceneGlobePrimitive = new MockPrimitive(largeSceneReusableGlobePrimitive, Pass.GLOBE); - largeScene.groundPrimitives.add(largeSceneDepthPrimitive); + largeScene.primitives.add(largeSceneGlobePrimitive); expect(largeScene).toRenderAndCall(function(rgba) { expect(arraySlice(rgba, 0, 4)).not.toEqual([0, 0, 0, 255]); expect(rgba[0]).toEqual(0); @@ -696,7 +749,6 @@ defineSuite([ scene.invertClassification = true; scene.invertClassificationColor = new Color(0.25, 0.25, 0.25, 1.0); - depthPrimitive.pass = Pass.CESIUM_3D_TILE; rectangleInstance.attributes.show = new ShowGeometryInstanceAttribute(true); primitive = new GroundPrimitive({ @@ -713,7 +765,7 @@ defineSuite([ invertedColor[2] = Color.floatToByte(Color.byteToFloat(depthColor[2]) * scene.invertClassificationColor.blue); invertedColor[3] = 255; - scene.groundPrimitives.add(depthPrimitive); + scene.primitives.add(tilesetPrimitive); expect(scene).toRender(invertedColor); scene.groundPrimitives.add(primitive); @@ -737,7 +789,6 @@ defineSuite([ scene.invertClassification = true; scene.invertClassificationColor = new Color(0.25, 0.25, 0.25, 0.25); - depthPrimitive.pass = Pass.CESIUM_3D_TILE; rectangleInstance.attributes.show = new ShowGeometryInstanceAttribute(true); primitive = new GroundPrimitive({ @@ -754,7 +805,7 @@ defineSuite([ invertedColor[2] = Color.floatToByte(Color.byteToFloat(depthColor[2]) * scene.invertClassificationColor.blue * scene.invertClassificationColor.alpha); invertedColor[3] = 255; - scene.groundPrimitives.add(depthPrimitive); + scene.primitives.add(tilesetPrimitive); expect(scene).toRender(invertedColor); scene.groundPrimitives.add(primitive); @@ -836,6 +887,10 @@ defineSuite([ verifyGroundPrimitiveRender(primitive, rectColor); + scene.primitives.destroyPrimitives = false; + scene.primitives.removeAll(); + scene.primitives.destroyPrimitives = true; + scene.groundPrimitives.destroyPrimitives = false; scene.groundPrimitives.removeAll(); scene.groundPrimitives.destroyPrimitives = true; @@ -862,6 +917,10 @@ defineSuite([ verifyGroundPrimitiveRender(primitive, rectColor); + scene.primitives.destroyPrimitives = false; + scene.primitives.removeAll(); + scene.primitives.destroyPrimitives = true; + scene.groundPrimitives.destroyPrimitives = false; scene.groundPrimitives.removeAll(); scene.groundPrimitives.destroyPrimitives = true; @@ -904,7 +963,7 @@ defineSuite([ asynchronous : false }); - scene.groundPrimitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); scene.groundPrimitives.add(primitive); scene.camera.setView({ destination : rect }); scene.renderForSpecs(); From 88b06bcec8ab7ec8ed095416f8ef7ff368322a54 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 19 Dec 2018 12:04:17 -0500 Subject: [PATCH 07/39] Cleanup Batch3dModel3DTileContentClassificationSpec --- ...d3DModel3DTileContentClassificationSpec.js | 81 +++++++++++-------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js b/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js index 5242838719b5..f697be22fbb1 100644 --- a/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js +++ b/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js @@ -47,33 +47,25 @@ defineSuite([ 'use strict'; var scene; - var modelMatrix; var centerLongitude = -1.31968; var centerLatitude = 0.698874; + var modelMatrix; var withBatchTableUrl = './Data/Cesium3DTiles/Batched/BatchedWithBatchTable/tileset.json'; var withBatchTableBinaryUrl = './Data/Cesium3DTiles/Batched/BatchedWithBatchTableBinary/tileset.json'; - function setCamera(longitude, latitude, offset) { + var globePrimitive; + var tilesetPrimitive; + var reusableGlobePrimitive; + var reusableTilesetPrimitive; + + function setCamera(longitude, latitude) { // One feature is located at the center, point the camera there var center = Cartesian3.fromRadians(longitude, latitude); scene.camera.lookAt(center, new HeadingPitchRange(0.0, -1.57, 15.0)); - scene.camera.moveUp(offset); - } - - function viewCenter() { - setCamera(centerLongitude, centerLatitude, 0.0); - } - - function viewGlobePrimitive() { - setCamera(centerLongitude, centerLatitude, 0.5); } - function view3DTilesPrimitive() { - setCamera(centerLongitude, centerLatitude, -0.5); - } - - function MockPrimitive(rectangle, pass) { + function createPrimitive(rectangle, pass) { var renderState; if (pass === Pass.CESIUM_3D_TILE) { renderState = RenderState.fromCache({ @@ -85,7 +77,7 @@ defineSuite([ }); } var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 0.0, 1.0)); - this._primitive = new Primitive({ + return new Primitive({ geometryInstances : new GeometryInstance({ geometry : new RectangleGeometry({ ellipsoid : Ellipsoid.WGS84, @@ -103,11 +95,19 @@ defineSuite([ }), asynchronous : false }); + } + function MockPrimitive(primitive, pass) { + this._primitive = primitive; this._pass = pass; + this.show = true; } MockPrimitive.prototype.update = function(frameState) { + if (!this.show) { + return; + } + var commandList = frameState.commandList; var startLength = commandList.length; this._primitive.update(frameState); @@ -123,7 +123,6 @@ defineSuite([ }; MockPrimitive.prototype.destroy = function() { - this._primitive.destroy(); return destroyObject(this); }; @@ -133,26 +132,34 @@ defineSuite([ var translation = Ellipsoid.WGS84.geodeticSurfaceNormalCartographic(new Cartographic(centerLongitude, centerLatitude)); Cartesian3.multiplyByScalar(translation, -5.0, translation); modelMatrix = Matrix4.fromTranslation(translation); + + var offset = CesiumMath.toRadians(0.01); + var rectangle = new Rectangle(centerLongitude - offset, centerLatitude - offset, centerLongitude + offset, centerLatitude + offset); + reusableGlobePrimitive = createPrimitive(rectangle, Pass.GLOBE); + reusableTilesetPrimitive = createPrimitive(rectangle, Pass.CESIUM_3D_TILE); }); afterAll(function() { + reusableGlobePrimitive.destroy(); + reusableTilesetPrimitive.destroy(); scene.destroyForSpecs(); }); beforeEach(function() { - var offset = CesiumMath.toRadians(0.01); - var rectangle1 = new Rectangle(centerLongitude - offset, centerLatitude, centerLongitude + offset, centerLatitude + offset); - var rectangle2 = new Rectangle(centerLongitude - offset, centerLatitude - offset, centerLongitude + offset, centerLatitude); + setCamera(centerLongitude, centerLatitude); - // wrap rectangle primitive so it gets executed during the globe pass or 3D Tiles pass to lay down depth - scene.primitives.add(new MockPrimitive(rectangle1, Pass.GLOBE)); - scene.primitives.add(new MockPrimitive(rectangle2, Pass.CESIUM_3D_TILE)); + // wrap rectangle primitive so it gets executed during the globe pass and 3D Tiles pass to lay down depth + globePrimitive = new MockPrimitive(reusableGlobePrimitive, Pass.GLOBE); + tilesetPrimitive = new MockPrimitive(reusableTilesetPrimitive, Pass.CESIUM_3D_TILE); - viewCenter(); + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); }); afterEach(function() { scene.primitives.removeAll(); + globePrimitive = globePrimitive && !globePrimitive.isDestroyed() && globePrimitive.destroy(); + tilesetPrimitive = tilesetPrimitive && !tilesetPrimitive.isDestroyed() && tilesetPrimitive.destroy(); }); it('classifies 3D Tiles', function() { @@ -160,9 +167,11 @@ defineSuite([ classificationType : ClassificationType.CESIUM_3D_TILE, modelMatrix : modelMatrix }).then(function(tileset) { - view3DTilesPrimitive(); + globePrimitive.show = false; + tilesetPrimitive.show = true; Cesium3DTilesTester.expectRenderTileset(scene, tileset); - viewGlobePrimitive(); + globePrimitive.show = true; + tilesetPrimitive.show = false; Cesium3DTilesTester.expectRenderBlank(scene, tileset); }); }); @@ -172,10 +181,14 @@ defineSuite([ classificationType : ClassificationType.TERRAIN, modelMatrix : modelMatrix }).then(function(tileset) { - view3DTilesPrimitive(); + globePrimitive.show = false; + tilesetPrimitive.show = true; Cesium3DTilesTester.expectRenderBlank(scene, tileset); - viewGlobePrimitive(); + globePrimitive.show = true; + tilesetPrimitive.show = false; Cesium3DTilesTester.expectRenderTileset(scene, tileset); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); @@ -184,10 +197,14 @@ defineSuite([ classificationType : ClassificationType.BOTH, modelMatrix : modelMatrix }).then(function(tileset) { - view3DTilesPrimitive(); + globePrimitive.show = false; + tilesetPrimitive.show = true; Cesium3DTilesTester.expectRenderTileset(scene, tileset); - viewGlobePrimitive(); + globePrimitive.show = true; + tilesetPrimitive.show = false; Cesium3DTilesTester.expectRenderTileset(scene, tileset); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); @@ -196,7 +213,6 @@ defineSuite([ classificationType : ClassificationType.BOTH, modelMatrix : modelMatrix }).then(function(tileset) { - view3DTilesPrimitive(); Cesium3DTilesTester.expectRenderTileset(scene, tileset); }); }); @@ -206,7 +222,6 @@ defineSuite([ classificationType : ClassificationType.BOTH, modelMatrix : modelMatrix }).then(function(tileset) { - view3DTilesPrimitive(); Cesium3DTilesTester.expectRenderTileset(scene, tileset); }); }); From 34e66f90fa43e1ceb7b87e38b1df90928c4d0c18 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 19 Dec 2018 12:09:06 -0500 Subject: [PATCH 08/39] Cleanup ClassificationModelSpec.js --- ...d3DModel3DTileContentClassificationSpec.js | 2 +- Specs/Scene/ClassificationModelSpec.js | 79 +++++++++++-------- 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js b/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js index f697be22fbb1..b01865967a94 100644 --- a/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js +++ b/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js @@ -47,9 +47,9 @@ defineSuite([ 'use strict'; var scene; + var modelMatrix; var centerLongitude = -1.31968; var centerLatitude = 0.698874; - var modelMatrix; var withBatchTableUrl = './Data/Cesium3DTiles/Batched/BatchedWithBatchTable/tileset.json'; var withBatchTableBinaryUrl = './Data/Cesium3DTiles/Batched/BatchedWithBatchTableBinary/tileset.json'; diff --git a/Specs/Scene/ClassificationModelSpec.js b/Specs/Scene/ClassificationModelSpec.js index 9fe30b35a07e..07bc16aa5f44 100644 --- a/Specs/Scene/ClassificationModelSpec.js +++ b/Specs/Scene/ClassificationModelSpec.js @@ -62,26 +62,18 @@ defineSuite([ var batchedModel = './Data/Models/Classification/batched.glb'; var quantizedModel = './Data/Models/Classification/batchedQuantization.glb'; - function setCamera(longitude, latitude, offset) { + var globePrimitive; + var tilesetPrimitive; + var reusableGlobePrimitive; + var reusableTilesetPrimitive; + + function setCamera(longitude, latitude) { // One feature is located at the center, point the camera there var center = Cartesian3.fromRadians(longitude, latitude); scene.camera.lookAt(center, new HeadingPitchRange(0.0, -1.57, 15.0)); - scene.camera.moveUp(offset); - } - - function viewCenter() { - setCamera(centerLongitude, centerLatitude, 0.0); - } - - function viewGlobePrimitive() { - setCamera(centerLongitude, centerLatitude, 0.5); - } - - function view3DTilesPrimitive() { - setCamera(centerLongitude, centerLatitude, -0.5); } - function MockPrimitive(rectangle, pass) { + function createPrimitive(rectangle, pass) { var renderState; if (pass === Pass.CESIUM_3D_TILE) { renderState = RenderState.fromCache({ @@ -93,7 +85,7 @@ defineSuite([ }); } var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 0.0, 0.0, 1.0)); - this._primitive = new Primitive({ + return new Primitive({ geometryInstances : new GeometryInstance({ geometry : new RectangleGeometry({ ellipsoid : Ellipsoid.WGS84, @@ -111,18 +103,26 @@ defineSuite([ }), asynchronous : false }); + } - this.pass = pass; + function MockPrimitive(primitive, pass) { + this._primitive = primitive; + this._pass = pass; + this.show = true; } MockPrimitive.prototype.update = function(frameState) { + if (!this.show) { + return; + } + var commandList = frameState.commandList; var startLength = commandList.length; this._primitive.update(frameState); for (var i = startLength; i < commandList.length; ++i) { var command = commandList[i]; - command.pass = this.pass; + command.pass = this._pass; } }; @@ -131,7 +131,6 @@ defineSuite([ }; MockPrimitive.prototype.destroy = function() { - this._primitive.destroy(); return destroyObject(this); }; @@ -141,26 +140,34 @@ defineSuite([ var translation = Ellipsoid.WGS84.geodeticSurfaceNormalCartographic(new Cartographic(centerLongitude, centerLatitude)); Cartesian3.multiplyByScalar(translation, -5.0, translation); modelMatrix = Matrix4.fromTranslation(translation); + + var offset = CesiumMath.toRadians(0.01); + var rectangle = new Rectangle(centerLongitude - offset, centerLatitude - offset, centerLongitude + offset, centerLatitude + offset); + reusableGlobePrimitive = createPrimitive(rectangle, Pass.GLOBE); + reusableTilesetPrimitive = createPrimitive(rectangle, Pass.CESIUM_3D_TILE); }); afterAll(function() { + reusableGlobePrimitive.destroy(); + reusableTilesetPrimitive.destroy(); scene.destroyForSpecs(); }); beforeEach(function() { - var offset = CesiumMath.toRadians(0.01); - var rectangle1 = new Rectangle(centerLongitude - offset, centerLatitude, centerLongitude + offset, centerLatitude + offset); - var rectangle2 = new Rectangle(centerLongitude - offset, centerLatitude - offset, centerLongitude + offset, centerLatitude); + setCamera(centerLongitude, centerLatitude); - // wrap rectangle primitive so it gets executed during the globe pass or 3D Tiles pass to lay down depth - scene.primitives.add(new MockPrimitive(rectangle1, Pass.GLOBE)); - scene.primitives.add(new MockPrimitive(rectangle2, Pass.CESIUM_3D_TILE)); + // wrap rectangle primitive so it gets executed during the globe pass and 3D Tiles pass to lay down depth + globePrimitive = new MockPrimitive(reusableGlobePrimitive, Pass.GLOBE); + tilesetPrimitive = new MockPrimitive(reusableTilesetPrimitive, Pass.CESIUM_3D_TILE); - viewCenter(); + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); }); afterEach(function() { scene.primitives.removeAll(); + globePrimitive = globePrimitive && !globePrimitive.isDestroyed() && globePrimitive.destroy(); + tilesetPrimitive = tilesetPrimitive && !tilesetPrimitive.isDestroyed() && tilesetPrimitive.destroy(); }); function expectRender(scene, model) { @@ -213,41 +220,45 @@ defineSuite([ it('classifies 3D Tiles', function() { return loadClassificationModel(batchedModel, ClassificationType.CESIUM_3D_TILE).then(function(model) { - view3DTilesPrimitive(); + globePrimitive.show = false; + tilesetPrimitive.show = true; expectRender(scene, model); - viewGlobePrimitive(); + globePrimitive.show = true; + tilesetPrimitive.show = false; expectRenderBlank(scene, model); }); }); it('classifies globe', function() { return loadClassificationModel(batchedModel, ClassificationType.TERRAIN).then(function(model) { - view3DTilesPrimitive(); + globePrimitive.show = false; + tilesetPrimitive.show = true; expectRenderBlank(scene, model); - viewGlobePrimitive(); + globePrimitive.show = true; + tilesetPrimitive.show = false; expectRender(scene, model); }); }); it('classifies both 3D Tiles and globe', function() { return loadClassificationModel(batchedModel, ClassificationType.BOTH).then(function(model) { - view3DTilesPrimitive(); + globePrimitive.show = false; + tilesetPrimitive.show = true; expectRender(scene, model); - viewGlobePrimitive(); + globePrimitive.show = true; + tilesetPrimitive.show = false; expectRender(scene, model); }); }); it('renders batched model', function() { return loadClassificationModel(batchedModel, ClassificationType.BOTH).then(function(model) { - view3DTilesPrimitive(); expectRender(scene, model); }); }); it('renders batched model with quantization', function() { return loadClassificationModel(quantizedModel, ClassificationType.BOTH).then(function(model) { - view3DTilesPrimitive(); expectRender(scene, model); }); }); From 2a2cef038587f62abf17cc5af3094ba6bed28fce Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 19 Dec 2018 12:24:25 -0500 Subject: [PATCH 09/39] Fix Geometry3DTileContent tests --- Specs/Scene/Geometry3DTileContentSpec.js | 213 ++++++++++++++++------- 1 file changed, 150 insertions(+), 63 deletions(-) diff --git a/Specs/Scene/Geometry3DTileContentSpec.js b/Specs/Scene/Geometry3DTileContentSpec.js index dae01c33c3cc..5b6cad6cc43e 100644 --- a/Specs/Scene/Geometry3DTileContentSpec.js +++ b/Specs/Scene/Geometry3DTileContentSpec.js @@ -14,12 +14,14 @@ defineSuite([ 'Core/RectangleGeometry', 'Core/Transforms', 'Renderer/Pass', + 'Renderer/RenderState', 'Scene/Cesium3DTileBatchTable', 'Scene/Cesium3DTileset', 'Scene/Cesium3DTileStyle', 'Scene/ClassificationType', 'Scene/PerInstanceColorAppearance', 'Scene/Primitive', + 'Scene/StencilConstants', 'Specs/Cesium3DTilesTester', 'Specs/createScene' ], function( @@ -38,12 +40,14 @@ defineSuite([ RectangleGeometry, Transforms, Pass, + RenderState, Cesium3DTileBatchTable, Cesium3DTileset, Cesium3DTileStyle, ClassificationType, PerInstanceColorAppearance, Primitive, + StencilConstants, Cesium3DTilesTester, createScene) { 'use strict'; @@ -82,73 +86,101 @@ defineSuite([ var scene; var rectangle; - var depthPrimitive; var tileset; + var globePrimitive; + var tilesetPrimitive; + var reusableGlobePrimitive; + var reusableTilesetPrimitive; + var depthColor; var ellipsoid = Ellipsoid.WGS84; - beforeAll(function() { - scene = createScene(); - }); - - afterAll(function() { - scene.destroyForSpecs(); - }); + function createPrimitive(rectangle, pass) { + var renderState; + if (pass === Pass.CESIUM_3D_TILE) { + renderState = RenderState.fromCache({ + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK, + depthTest : { + enabled : true + } + }); + } + var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 0.0, 0.0, 1.0)); + depthColor = depthColorAttribute.value; + return new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new RectangleGeometry({ + ellipsoid : Ellipsoid.WGS84, + rectangle : rectangle + }), + id : 'depth rectangle', + attributes : { + color : depthColorAttribute + } + }), + appearance : new PerInstanceColorAppearance({ + translucent : false, + flat : true, + renderState : renderState + }), + asynchronous : false + }); + } - function MockGlobePrimitive(primitive) { + function MockPrimitive(primitive, pass) { this._primitive = primitive; - this.pass = Pass.CESIUM_3D_TILE; + this._pass = pass; + this.show = true; } - MockGlobePrimitive.prototype.update = function(frameState) { + MockPrimitive.prototype.update = function(frameState) { + if (!this.show) { + return; + } + var commandList = frameState.commandList; var startLength = commandList.length; this._primitive.update(frameState); for (var i = startLength; i < commandList.length; ++i) { var command = commandList[i]; - command.pass = this.pass; + command.pass = this._pass; } }; - MockGlobePrimitive.prototype.isDestroyed = function() { + MockPrimitive.prototype.isDestroyed = function() { return false; }; - MockGlobePrimitive.prototype.destroy = function() { - this._primitive.destroy(); + MockPrimitive.prototype.destroy = function() { return destroyObject(this); }; - beforeEach(function() { + beforeAll(function() { + scene = createScene(); + rectangle = Rectangle.fromDegrees(-40.0, -40.0, 40.0, 40.0); + reusableGlobePrimitive = createPrimitive(rectangle, Pass.GLOBE); + reusableTilesetPrimitive = createPrimitive(rectangle, Pass.CESIUM_3D_TILE); + }); - var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 0.0, 0.0, 1.0)); - var primitive = new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : rectangle - }), - id : 'depth rectangle', - attributes : { - color : depthColorAttribute - } - }), - appearance : new PerInstanceColorAppearance({ - translucent : false, - flat : true - }), - asynchronous : false - }); + afterAll(function() { + reusableGlobePrimitive.destroy(); + reusableTilesetPrimitive.destroy(); + scene.destroyForSpecs(); + }); - // wrap rectangle primitive so it gets executed during the globe pass to lay down depth - depthPrimitive = new MockGlobePrimitive(primitive); + beforeEach(function() { + // wrap rectangle primitive so it gets executed during the globe pass and 3D Tiles pass to lay down depth + globePrimitive = new MockPrimitive(reusableGlobePrimitive, Pass.GLOBE); + tilesetPrimitive = new MockPrimitive(reusableTilesetPrimitive, Pass.CESIUM_3D_TILE); }); afterEach(function() { scene.primitives.removeAll(); - depthPrimitive = depthPrimitive && !depthPrimitive.isDestroyed() && depthPrimitive.destroy(); + globePrimitive = globePrimitive && !globePrimitive.isDestroyed() && globePrimitive.destroy(); + tilesetPrimitive = tilesetPrimitive && !tilesetPrimitive.isDestroyed() && tilesetPrimitive.destroy(); tileset = tileset && !tileset.isDestroyed() && tileset.destroy(); }); @@ -236,8 +268,63 @@ defineSuite([ expectRender(scene, [0, 0, 255, 255]); } + it('renders on 3D Tiles', function() { + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); + tileset = scene.primitives.add(new Cesium3DTileset({ + url : geometryBoxes, + classificationType : ClassificationType.CESIUM_3D_TILE + })); + return loadTileset(tileset).then(function(tileset) { + globePrimitive.show = false; + tilesetPrimitive.show = true; + verifyRender(tileset, scene); + verifyPick(scene); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expect(scene).toRender(depthColor); + }); + }); + + it('renders on globe', function() { + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); + tileset = scene.primitives.add(new Cesium3DTileset({ + url : geometryBoxes, + classificationType : ClassificationType.TERRAIN + })); + return loadTileset(tileset).then(function(tileset) { + globePrimitive.show = false; + tilesetPrimitive.show = true; + expect(scene).toRender(depthColor); + globePrimitive.show = true; + tilesetPrimitive.show = false; + verifyRender(tileset, scene); + verifyPick(scene); + }); + }); + + it('renders on 3D Tiles and globe', function() { + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); + tileset = scene.primitives.add(new Cesium3DTileset({ + url : geometryBoxes, + classificationType : ClassificationType.BOTH + })); + return loadTileset(tileset).then(function(tileset) { + globePrimitive.show = false; + tilesetPrimitive.show = true; + verifyRender(tileset, scene); + verifyPick(scene); + globePrimitive.show = true; + tilesetPrimitive.show = false; + verifyRender(tileset, scene); + verifyPick(scene); + }); + }); + it('renders boxes', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryBoxes })); @@ -248,7 +335,7 @@ defineSuite([ }); it('renders batched boxes', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryBoxesBatchedChildren })); @@ -259,7 +346,7 @@ defineSuite([ }); it('renders boxes with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryBoxesWithBatchTable })); @@ -270,7 +357,7 @@ defineSuite([ }); it('renders batched boxes with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryBoxesBatchedChildrenWithBatchTable })); @@ -281,7 +368,7 @@ defineSuite([ }); it('renders boxes with batch ids', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryBoxesWithBatchIds })); @@ -292,7 +379,7 @@ defineSuite([ }); it('renders cylinders', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryCylinders })); @@ -303,7 +390,7 @@ defineSuite([ }); it('renders batched cylinders', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryCylindersBatchedChildren })); @@ -314,7 +401,7 @@ defineSuite([ }); it('renders cylinders with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryCylindersWithBatchTable })); @@ -325,7 +412,7 @@ defineSuite([ }); it('renders batched cylinders with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryCylindersBatchedChildrenWithBatchTable })); @@ -336,7 +423,7 @@ defineSuite([ }); it('renders cylinders with batch ids', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryCylindersWithBatchIds })); @@ -347,7 +434,7 @@ defineSuite([ }); it('renders ellipsoids', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryEllipsoids })); @@ -358,7 +445,7 @@ defineSuite([ }); it('renders batched ellipsoids', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryEllipsoidsBatchedChildren })); @@ -369,7 +456,7 @@ defineSuite([ }); it('renders ellipsoids with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryEllipsoidsWithBatchTable })); @@ -380,7 +467,7 @@ defineSuite([ }); it('renders batched ellipsoids with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryEllipsoidsBatchedChildrenWithBatchTable })); @@ -391,7 +478,7 @@ defineSuite([ }); it('renders ellipsoids with batch ids', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryEllipsoidsWithBatchIds })); @@ -402,7 +489,7 @@ defineSuite([ }); it('renders spheres', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometrySpheres })); @@ -413,7 +500,7 @@ defineSuite([ }); it('renders batched spheres', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometrySpheresBatchedChildren })); @@ -424,7 +511,7 @@ defineSuite([ }); it('renders spheres with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometrySpheresWithBatchTable })); @@ -435,7 +522,7 @@ defineSuite([ }); it('renders batched spheres with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometrySpheresBatchedChildrenWithBatchTable })); @@ -446,7 +533,7 @@ defineSuite([ }); it('renders spheres with batch ids', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometrySpheresWithBatchIds })); @@ -457,7 +544,7 @@ defineSuite([ }); it('renders all geometries', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryAll })); @@ -468,7 +555,7 @@ defineSuite([ }); it('renders batched all geometries', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryAllBatchedChildren })); @@ -479,7 +566,7 @@ defineSuite([ }); it('renders all geometries with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryAllWithBatchTable })); @@ -490,7 +577,7 @@ defineSuite([ }); it('renders batched all geometries with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryAllBatchedChildrenWithBatchTable })); @@ -501,7 +588,7 @@ defineSuite([ }); it('renders all geometries with batch ids', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryAllWithBatchIds })); @@ -512,7 +599,7 @@ defineSuite([ }); it('renders all geometries with debug color', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : geometryAllWithBatchTable, debugColorizeTiles : true From 8163a791f84f0203c99baddf0c0dfae9a487dc38 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 19 Dec 2018 12:30:23 -0500 Subject: [PATCH 10/39] Fix Vector3DTileContent tests --- Specs/Scene/Vector3DTileContentSpec.js | 193 ++++++++++++++++--------- 1 file changed, 121 insertions(+), 72 deletions(-) diff --git a/Specs/Scene/Vector3DTileContentSpec.js b/Specs/Scene/Vector3DTileContentSpec.js index e4f2cbc69257..c427224a9db1 100644 --- a/Specs/Scene/Vector3DTileContentSpec.js +++ b/Specs/Scene/Vector3DTileContentSpec.js @@ -14,12 +14,14 @@ defineSuite([ 'Core/RectangleGeometry', 'Core/Transforms', 'Renderer/Pass', + 'Renderer/RenderState', 'Scene/Cesium3DTileBatchTable', 'Scene/Cesium3DTileset', 'Scene/Cesium3DTileStyle', 'Scene/ClassificationType', 'Scene/PerInstanceColorAppearance', 'Scene/Primitive', + 'Scene/StencilConstants', 'Specs/Cesium3DTilesTester', 'Specs/createScene' ], function( @@ -38,12 +40,14 @@ defineSuite([ RectangleGeometry, Transforms, Pass, + RenderState, Cesium3DTileBatchTable, Cesium3DTileset, Cesium3DTileStyle, ClassificationType, PerInstanceColorAppearance, Primitive, + StencilConstants, Cesium3DTilesTester, createScene) { 'use strict'; @@ -74,73 +78,101 @@ defineSuite([ var scene; var rectangle; - var depthPrimitive; var tileset; + var globePrimitive; + var tilesetPrimitive; + var reusableGlobePrimitive; + var reusableTilesetPrimitive; + var depthColor; var ellipsoid = Ellipsoid.WGS84; - beforeAll(function() { - scene = createScene(); - }); - - afterAll(function() { - scene.destroyForSpecs(); - }); + function createPrimitive(rectangle, pass) { + var renderState; + if (pass === Pass.CESIUM_3D_TILE) { + renderState = RenderState.fromCache({ + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK, + depthTest : { + enabled : true + } + }); + } + var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 0.0, 0.0, 1.0)); + depthColor = depthColorAttribute.value; + return new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new RectangleGeometry({ + ellipsoid : Ellipsoid.WGS84, + rectangle : rectangle + }), + id : 'depth rectangle', + attributes : { + color : depthColorAttribute + } + }), + appearance : new PerInstanceColorAppearance({ + translucent : false, + flat : true, + renderState : renderState + }), + asynchronous : false + }); + } - function MockGlobePrimitive(primitive) { + function MockPrimitive(primitive, pass) { this._primitive = primitive; - this.pass = Pass.CESIUM_3D_TILE; + this._pass = pass; + this.show = true; } - MockGlobePrimitive.prototype.update = function(frameState) { + MockPrimitive.prototype.update = function(frameState) { + if (!this.show) { + return; + } + var commandList = frameState.commandList; var startLength = commandList.length; this._primitive.update(frameState); for (var i = startLength; i < commandList.length; ++i) { var command = commandList[i]; - command.pass = this.pass; + command.pass = this._pass; } }; - MockGlobePrimitive.prototype.isDestroyed = function() { + MockPrimitive.prototype.isDestroyed = function() { return false; }; - MockGlobePrimitive.prototype.destroy = function() { - this._primitive.destroy(); + MockPrimitive.prototype.destroy = function() { return destroyObject(this); }; - beforeEach(function() { + beforeAll(function() { + scene = createScene(); + rectangle = Rectangle.fromDegrees(-40.0, -40.0, 40.0, 40.0); + reusableGlobePrimitive = createPrimitive(rectangle, Pass.GLOBE); + reusableTilesetPrimitive = createPrimitive(rectangle, Pass.CESIUM_3D_TILE); + }); - var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 0.0, 0.0, 1.0)); - var primitive = new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : rectangle - }), - id : 'depth rectangle', - attributes : { - color : depthColorAttribute - } - }), - appearance : new PerInstanceColorAppearance({ - translucent : false, - flat : true - }), - asynchronous : false - }); + afterAll(function() { + reusableGlobePrimitive.destroy(); + reusableTilesetPrimitive.destroy(); + scene.destroyForSpecs(); + }); - // wrap rectangle primitive so it gets executed during the globe pass to lay down depth - depthPrimitive = new MockGlobePrimitive(primitive); + beforeEach(function() { + // wrap rectangle primitive so it gets executed during the globe pass and 3D Tiles pass to lay down depth + globePrimitive = new MockPrimitive(reusableGlobePrimitive, Pass.GLOBE); + tilesetPrimitive = new MockPrimitive(reusableTilesetPrimitive, Pass.CESIUM_3D_TILE); }); afterEach(function() { scene.primitives.removeAll(); - depthPrimitive = depthPrimitive && !depthPrimitive.isDestroyed() && depthPrimitive.destroy(); + globePrimitive = globePrimitive && !globePrimitive.isDestroyed() && globePrimitive.destroy(); + tilesetPrimitive = tilesetPrimitive && !tilesetPrimitive.isDestroyed() && tilesetPrimitive.destroy(); tileset = tileset && !tileset.isDestroyed() && tileset.destroy(); }); @@ -461,7 +493,7 @@ defineSuite([ }); it('renders polygons', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : vectorPolygons })); @@ -472,7 +504,7 @@ defineSuite([ }); it('renders batched polygons', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : vectorPolygonsBatchedChildren })); @@ -483,7 +515,7 @@ defineSuite([ }); it('renders polygons with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : vectorPolygonsWithBatchTable })); @@ -494,7 +526,7 @@ defineSuite([ }); it('renders batched polygons with a batch table', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : vectorPolygonsBatchedChildrenWithBatchTable })); @@ -505,7 +537,7 @@ defineSuite([ }); it('renders polygons with batch ids', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : vectorPolygonsWithBatchIds })); @@ -561,7 +593,7 @@ defineSuite([ }); it('renders combined tile', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : vectorCombined })); @@ -571,7 +603,7 @@ defineSuite([ }); it('renders combined tile with batch ids', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : vectorCombinedWithBatchIds })); @@ -581,7 +613,7 @@ defineSuite([ }); it('renders with debug color', function() { - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : vectorCombined, debugColorizeTiles : true @@ -603,41 +635,58 @@ defineSuite([ }); }); - it('renders with different classification types', function() { - scene.primitives.add(depthPrimitive); + it('renders on 3D Tiles', function() { + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); tileset = scene.primitives.add(new Cesium3DTileset({ url : vectorPolygonsBatchedChildren, classificationType : ClassificationType.CESIUM_3D_TILE })); return loadTileset(tileset).then(function(tileset) { + globePrimitive.show = false; + tilesetPrimitive.show = true; + verifyRender(tileset, scene); + verifyPick(scene); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expect(scene).toRender(depthColor); + }); + }); + + it('renders on globe', function() { + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); + tileset = scene.primitives.add(new Cesium3DTileset({ + url : vectorPolygonsBatchedChildren, + classificationType : ClassificationType.TERRAIN + })); + return loadTileset(tileset).then(function(tileset) { + globePrimitive.show = false; + tilesetPrimitive.show = true; + expect(scene).toRender(depthColor); + globePrimitive.show = true; + tilesetPrimitive.show = false; verifyRender(tileset, scene); verifyPick(scene); + }); + }); - scene.primitives.remove(tileset); - - tileset = scene.primitives.add(new Cesium3DTileset({ - url : vectorPolygonsBatchedChildren, - classificationType : ClassificationType.TERRAIN - })); - return loadTileset(tileset).then(function(tileset) { - depthPrimitive.pass = Pass.GLOBE; - verifyRender(tileset, scene); - verifyPick(scene); - - scene.primitives.remove(tileset); - - tileset = scene.primitives.add(new Cesium3DTileset({ - url : vectorPolygonsBatchedChildren, - classificationType : ClassificationType.BOTH - })); - return loadTileset(tileset).then(function(tileset) { - verifyRender(tileset, scene); - verifyPick(scene); - depthPrimitive.pass = Pass.CESIUM_3D_TILE; - verifyRender(tileset, scene); - verifyPick(scene); - }); - }); + it('renders on 3D Tiles and globe', function() { + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); + tileset = scene.primitives.add(new Cesium3DTileset({ + url : vectorPolygonsBatchedChildren, + classificationType : ClassificationType.BOTH + })); + return loadTileset(tileset).then(function(tileset) { + globePrimitive.show = false; + tilesetPrimitive.show = true; + verifyRender(tileset, scene); + verifyPick(scene); + globePrimitive.show = true; + tilesetPrimitive.show = false; + verifyRender(tileset, scene); + verifyPick(scene); }); }); From 99beaaad278af89718861664a4deac69a8f8549d Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 19 Dec 2018 13:28:39 -0500 Subject: [PATCH 11/39] Fixed Vector3DTileGeometry tests --- Specs/Scene/Geometry3DTileContentSpec.js | 6 + Specs/Scene/Vector3DTileContentSpec.js | 6 + Specs/Scene/Vector3DTileGeometrySpec.js | 180 +++++++++++++++++------ 3 files changed, 148 insertions(+), 44 deletions(-) diff --git a/Specs/Scene/Geometry3DTileContentSpec.js b/Specs/Scene/Geometry3DTileContentSpec.js index 5b6cad6cc43e..d0467d993867 100644 --- a/Specs/Scene/Geometry3DTileContentSpec.js +++ b/Specs/Scene/Geometry3DTileContentSpec.js @@ -283,6 +283,8 @@ defineSuite([ globePrimitive.show = true; tilesetPrimitive.show = false; expect(scene).toRender(depthColor); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); @@ -301,6 +303,8 @@ defineSuite([ tilesetPrimitive.show = false; verifyRender(tileset, scene); verifyPick(scene); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); @@ -320,6 +324,8 @@ defineSuite([ tilesetPrimitive.show = false; verifyRender(tileset, scene); verifyPick(scene); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); diff --git a/Specs/Scene/Vector3DTileContentSpec.js b/Specs/Scene/Vector3DTileContentSpec.js index c427224a9db1..079c543159c5 100644 --- a/Specs/Scene/Vector3DTileContentSpec.js +++ b/Specs/Scene/Vector3DTileContentSpec.js @@ -650,6 +650,8 @@ defineSuite([ globePrimitive.show = true; tilesetPrimitive.show = false; expect(scene).toRender(depthColor); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); @@ -668,6 +670,8 @@ defineSuite([ tilesetPrimitive.show = false; verifyRender(tileset, scene); verifyPick(scene); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); @@ -687,6 +691,8 @@ defineSuite([ tilesetPrimitive.show = false; verifyRender(tileset, scene); verifyPick(scene); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); diff --git a/Specs/Scene/Vector3DTileGeometrySpec.js b/Specs/Scene/Vector3DTileGeometrySpec.js index 233317192880..d28b4e18fbf3 100644 --- a/Specs/Scene/Vector3DTileGeometrySpec.js +++ b/Specs/Scene/Vector3DTileGeometrySpec.js @@ -13,10 +13,13 @@ defineSuite([ 'Core/RectangleGeometry', 'Core/Transforms', 'Renderer/Pass', + 'Renderer/RenderState', 'Scene/Cesium3DTileBatchTable', + 'Scene/ClassificationType', 'Scene/ColorBlendMode', 'Scene/PerInstanceColorAppearance', 'Scene/Primitive', + 'Scene/StencilConstants', 'Specs/createContext', 'Specs/createScene', 'Specs/pollToPromise' @@ -35,10 +38,13 @@ defineSuite([ RectangleGeometry, Transforms, Pass, + RenderState, Cesium3DTileBatchTable, + ClassificationType, ColorBlendMode, PerInstanceColorAppearance, Primitive, + StencilConstants, createContext, createScene, pollToPromise) { @@ -57,19 +63,14 @@ defineSuite([ var scene; var rectangle; - var depthPrimitive; var geometry; + var globePrimitive; + var tilesetPrimitive; + var reusableGlobePrimitive; + var reusableTilesetPrimitive; var ellipsoid = Ellipsoid.WGS84; - beforeAll(function() { - scene = createScene({ contextOptions : contextOptions }); - }); - - afterAll(function() { - scene.destroyForSpecs(); - }); - var mockTileset = { _statistics : { texturesByteLength : 0 @@ -83,61 +84,92 @@ defineSuite([ getFeature : function(id) { return { batchId : id }; } }; - function MockGlobePrimitive(primitive) { + function createPrimitive(rectangle, pass) { + var renderState; + if (pass === Pass.CESIUM_3D_TILE) { + renderState = RenderState.fromCache({ + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK, + depthTest : { + enabled : true + } + }); + } + var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 0.0, 0.0, 1.0)); + return new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new RectangleGeometry({ + ellipsoid : Ellipsoid.WGS84, + rectangle : rectangle + }), + id : 'depth rectangle', + attributes : { + color : depthColorAttribute + } + }), + appearance : new PerInstanceColorAppearance({ + translucent : false, + flat : true, + renderState : renderState + }), + asynchronous : false + }); + } + + function MockPrimitive(primitive, pass) { this._primitive = primitive; - this.pass = Pass.CESIUM_3D_TILE; + this._pass = pass; + this.show = true; } - MockGlobePrimitive.prototype.update = function(frameState) { + MockPrimitive.prototype.update = function(frameState) { + if (!this.show) { + return; + } + var commandList = frameState.commandList; var startLength = commandList.length; this._primitive.update(frameState); for (var i = startLength; i < commandList.length; ++i) { var command = commandList[i]; - command.pass = this.pass; + command.pass = this._pass; } }; - MockGlobePrimitive.prototype.isDestroyed = function() { + MockPrimitive.prototype.isDestroyed = function() { return false; }; - MockGlobePrimitive.prototype.destroy = function() { - this._primitive.destroy(); + MockPrimitive.prototype.destroy = function() { return destroyObject(this); }; - beforeEach(function() { + beforeAll(function() { + scene = createScene({ contextOptions : contextOptions }); + rectangle = Rectangle.fromDegrees(-80.0, 20.0, -70.0, 30.0); + reusableGlobePrimitive = createPrimitive(rectangle, Pass.GLOBE); + reusableTilesetPrimitive = createPrimitive(rectangle, Pass.CESIUM_3D_TILE); + }); - var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 0.0, 0.0, 1.0)); - var primitive = new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : rectangle - }), - id : 'depth rectangle', - attributes : { - color : depthColorAttribute - } - }), - appearance : new PerInstanceColorAppearance({ - translucent : false, - flat : true - }), - asynchronous : false - }); + afterAll(function() { + reusableGlobePrimitive.destroy(); + reusableTilesetPrimitive.destroy(); + scene.destroyForSpecs(); + }); - // wrap rectangle primitive so it gets executed during the globe pass to lay down depth - depthPrimitive = new MockGlobePrimitive(primitive); + beforeEach(function() { + // wrap rectangle primitive so it gets executed during the globe pass and 3D Tiles pass to lay down depth + globePrimitive = new MockPrimitive(reusableGlobePrimitive, Pass.GLOBE); + tilesetPrimitive = new MockPrimitive(reusableTilesetPrimitive, Pass.CESIUM_3D_TILE); }); afterEach(function() { scene.primitives.removeAll(); + globePrimitive = globePrimitive && !globePrimitive.isDestroyed() && globePrimitive.destroy(); + tilesetPrimitive = tilesetPrimitive && !tilesetPrimitive.isDestroyed() && tilesetPrimitive.destroy(); geometry = geometry && !geometry.isDestroyed() && geometry.destroy(); - depthPrimitive = depthPrimitive && !depthPrimitive.isDestroyed() && depthPrimitive.destroy(); }); function loadGeometries(geometries) { @@ -217,7 +249,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, 1); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); geometry = scene.primitives.add(new Vector3DTileGeometry(combine(geometryOptions, { center : center, @@ -249,7 +281,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, length); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); geometry = scene.primitives.add(new Vector3DTileGeometry(combine(geometryOptions, { center : center, @@ -533,7 +565,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, length); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); geometry = scene.primitives.add(new Vector3DTileGeometry({ boxes : boxes, @@ -587,7 +619,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, 1); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(tilesetPrimitive); geometry = scene.primitives.add(new Vector3DTileGeometry({ ellipsoids : ellipsoids, @@ -620,7 +652,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, 1); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); geometry = scene.primitives.add(new Vector3DTileGeometry({ ellipsoids : packEllipsoids([{ @@ -648,6 +680,66 @@ defineSuite([ }); }); + it('renders based on classificationType' + webglMessage, function() { + var radii = new Cartesian3(100.0, 100.0, 1000.0); + var ellipsoids = packEllipsoids([{ + modelMatrix : Matrix4.IDENTITY, + radii : radii + }]); + var ellipsoidBatchIds = new Uint16Array([0]); + + var origin = Rectangle.center(rectangle); + var center = ellipsoid.cartographicToCartesian(origin); + var modelMatrix = Transforms.eastNorthUpToFixedFrame(center); + + var bv = new BoundingSphere(center, Cartesian3.maximumComponent(radii)); + + var batchTable = new Cesium3DTileBatchTable(mockTileset, 1); + batchTable.update(mockTileset, scene.frameState); + + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); + + geometry = scene.primitives.add(new Vector3DTileGeometry({ + ellipsoids : ellipsoids, + ellipsoidBatchIds : ellipsoidBatchIds, + boundingVolume : bv, + center : center, + modelMatrix : modelMatrix, + batchTable : batchTable + })); + return loadGeometries(geometry).then(function() { + scene.camera.lookAtTransform(modelMatrix, new Cartesian3(0.0, 0.0, 1.0)); + + geometry.classificationType = ClassificationType.CESIUM_3D_TILE; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expect(scene).toRender([255, 255, 255, 255]); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expect(scene).toRender([255, 0, 0, 255]); + + geometry.classificationType = ClassificationType.TERRAIN; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expect(scene).toRender([255, 0, 0, 255]); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expect(scene).toRender([255, 255, 255, 255]); + + geometry.classificationType = ClassificationType.BOTH; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expect(scene).toRender([255, 255, 255, 255]); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expect(scene).toRender([255, 255, 255, 255]); + + globePrimitive.show = true; + tilesetPrimitive.show = true; + }); + }); + it('picks geometry' + webglMessage, function() { var origin = Rectangle.center(rectangle); var center = ellipsoid.cartographicToCartesian(origin); @@ -655,7 +747,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, 1); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); geometry = scene.primitives.add(new Vector3DTileGeometry({ ellipsoids : packEllipsoids([{ From 07e4093edbfa517cc4c0be776b6fe0c22259e8df Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 19 Dec 2018 13:39:41 -0500 Subject: [PATCH 12/39] Change default classification type of Vector3DTileGeoemtry and Vector3DTilePolygon to BOTH --- Source/Scene/Vector3DTileGeometry.js | 4 ++-- Source/Scene/Vector3DTilePolygons.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Scene/Vector3DTileGeometry.js b/Source/Scene/Vector3DTileGeometry.js index bb1e7e2e7084..8569dc92ce95 100644 --- a/Source/Scene/Vector3DTileGeometry.js +++ b/Source/Scene/Vector3DTileGeometry.js @@ -114,9 +114,9 @@ define([ /** * What this tile will classify. * @type {ClassificationType} - * @default ClassificationType.CESIUM_3D_TILE + * @default ClassificationType.BOTH */ - this.classificationType = ClassificationType.CESIUM_3D_TILE; + this.classificationType = ClassificationType.BOTH; } defineProperties(Vector3DTileGeometry.prototype, { diff --git a/Source/Scene/Vector3DTilePolygons.js b/Source/Scene/Vector3DTilePolygons.js index dd1dce43fba2..a74b8988cd67 100644 --- a/Source/Scene/Vector3DTilePolygons.js +++ b/Source/Scene/Vector3DTilePolygons.js @@ -120,9 +120,9 @@ define([ /** * What this tile will classify. * @type {ClassificationType} - * @default ClassificationType.CESIUM_3D_TILE + * @default ClassificationType.BOTH */ - this.classificationType = ClassificationType.CESIUM_3D_TILE; + this.classificationType = ClassificationType.BOTH; } defineProperties(Vector3DTilePolygons.prototype, { From 3f6ae77806a2e90dbabf5679fe037c6cf1cf3bcc Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 19 Dec 2018 13:45:05 -0500 Subject: [PATCH 13/39] Added tests for Vector3DTilePolygons --- Specs/Scene/Vector3DTilePolygonsSpec.js | 177 ++++++++++++++++++------ 1 file changed, 132 insertions(+), 45 deletions(-) diff --git a/Specs/Scene/Vector3DTilePolygonsSpec.js b/Specs/Scene/Vector3DTilePolygonsSpec.js index d7f9d0b28598..767e8642ae82 100644 --- a/Specs/Scene/Vector3DTilePolygonsSpec.js +++ b/Specs/Scene/Vector3DTilePolygonsSpec.js @@ -14,10 +14,13 @@ defineSuite([ 'Core/RectangleGeometry', 'Core/Transforms', 'Renderer/Pass', + 'Renderer/RenderState', 'Scene/Cesium3DTileBatchTable', + 'Scene/ClassificationType', 'Scene/ColorBlendMode', 'Scene/PerInstanceColorAppearance', 'Scene/Primitive', + 'Scene/StencilConstants', 'Specs/createContext', 'Specs/createScene', 'Specs/pollToPromise' @@ -37,10 +40,13 @@ defineSuite([ RectangleGeometry, Transforms, Pass, + RenderState, Cesium3DTileBatchTable, + ClassificationType, ColorBlendMode, PerInstanceColorAppearance, Primitive, + StencilConstants, createContext, createScene, pollToPromise) { @@ -59,19 +65,14 @@ defineSuite([ var scene; var rectangle; - var depthPrimitive; var polygons; + var globePrimitive; + var tilesetPrimitive; + var reusableGlobePrimitive; + var reusableTilesetPrimitive; var ellipsoid = Ellipsoid.WGS84; - beforeAll(function() { - scene = createScene({ contextOptions : contextOptions }); - }); - - afterAll(function() { - scene.destroyForSpecs(); - }); - var mockTileset = { _statistics : { texturesByteLength : 0 @@ -85,61 +86,92 @@ defineSuite([ getFeature : function(id) { return { batchId : id }; } }; - function MockGlobePrimitive(primitive) { + function createPrimitive(rectangle, pass) { + var renderState; + if (pass === Pass.CESIUM_3D_TILE) { + renderState = RenderState.fromCache({ + stencilTest : StencilConstants.setCesium3DTileBit(), + stencilMask : StencilConstants.CESIUM_3D_TILE_MASK, + depthTest : { + enabled : true + } + }); + } + var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 0.0, 0.0, 1.0)); + return new Primitive({ + geometryInstances : new GeometryInstance({ + geometry : new RectangleGeometry({ + ellipsoid : Ellipsoid.WGS84, + rectangle : rectangle + }), + id : 'depth rectangle', + attributes : { + color : depthColorAttribute + } + }), + appearance : new PerInstanceColorAppearance({ + translucent : false, + flat : true, + renderState : renderState + }), + asynchronous : false + }); + } + + function MockPrimitive(primitive, pass) { this._primitive = primitive; - this.pass = Pass.CESIUM_3D_TILE; + this._pass = pass; + this.show = true; } - MockGlobePrimitive.prototype.update = function(frameState) { + MockPrimitive.prototype.update = function(frameState) { + if (!this.show) { + return; + } + var commandList = frameState.commandList; var startLength = commandList.length; this._primitive.update(frameState); for (var i = startLength; i < commandList.length; ++i) { var command = commandList[i]; - command.pass = this.pass; + command.pass = this._pass; } }; - MockGlobePrimitive.prototype.isDestroyed = function() { + MockPrimitive.prototype.isDestroyed = function() { return false; }; - MockGlobePrimitive.prototype.destroy = function() { - this._primitive.destroy(); + MockPrimitive.prototype.destroy = function() { return destroyObject(this); }; - beforeEach(function() { + beforeAll(function() { + scene = createScene({ contextOptions : contextOptions }); + rectangle = Rectangle.fromDegrees(-40.0, -40.0, 40.0, 40.0); + reusableGlobePrimitive = createPrimitive(rectangle, Pass.GLOBE); + reusableTilesetPrimitive = createPrimitive(rectangle, Pass.CESIUM_3D_TILE); + }); - var depthColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 0.0, 0.0, 1.0)); - var primitive = new Primitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : rectangle - }), - id : 'depth rectangle', - attributes : { - color : depthColorAttribute - } - }), - appearance : new PerInstanceColorAppearance({ - translucent : false, - flat : true - }), - asynchronous : false - }); + afterAll(function() { + reusableGlobePrimitive.destroy(); + reusableTilesetPrimitive.destroy(); + scene.destroyForSpecs(); + }); - // wrap rectangle primitive so it gets executed during the globe pass to lay down depth - depthPrimitive = new MockGlobePrimitive(primitive); + beforeEach(function() { + // wrap rectangle primitive so it gets executed during the globe pass and 3D Tiles pass to lay down depth + globePrimitive = new MockPrimitive(reusableGlobePrimitive, Pass.GLOBE); + tilesetPrimitive = new MockPrimitive(reusableTilesetPrimitive, Pass.CESIUM_3D_TILE); }); afterEach(function() { scene.primitives.removeAll(); + globePrimitive = globePrimitive && !globePrimitive.isDestroyed() && globePrimitive.destroy(); + tilesetPrimitive = tilesetPrimitive && !tilesetPrimitive.isDestroyed() && tilesetPrimitive.destroy(); polygons = polygons && !polygons.isDestroyed() && polygons.destroy(); - depthPrimitive = depthPrimitive && !depthPrimitive.isDestroyed() && depthPrimitive.destroy(); }); function loadPolygons(polygons) { @@ -211,7 +243,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, 1); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); var center = ellipsoid.cartographicToCartesian(Rectangle.center(rectangle)); polygons = scene.primitives.add(new Vector3DTilePolygons(combine(polygonOptions, { @@ -256,7 +288,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, 2); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); var center = ellipsoid.cartographicToCartesian(Rectangle.center(rectangle)); polygons = scene.primitives.add(new Vector3DTilePolygons({ @@ -316,7 +348,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, 2); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); var center = ellipsoid.cartographicToCartesian(Rectangle.center(rectangle)); polygons = scene.primitives.add(new Vector3DTilePolygons({ @@ -377,7 +409,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, 2); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); var center = ellipsoid.cartographicToCartesian(Rectangle.center(rectangle)); polygons = scene.primitives.add(new Vector3DTilePolygons({ @@ -424,7 +456,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, 1); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(tilesetPrimitive); var center = ellipsoid.cartographicToCartesian(Rectangle.center(rectangle)); polygons = scene.primitives.add(new Vector3DTilePolygons(combine(polygonOptions, { @@ -465,7 +497,7 @@ defineSuite([ var batchTable = new Cesium3DTileBatchTable(mockTileset, 1); batchTable.update(mockTileset, scene.frameState); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); var center = ellipsoid.cartographicToCartesian(Rectangle.center(rectangle)); polygons = scene.primitives.add(new Vector3DTilePolygons(combine(polygonOptions, { @@ -493,13 +525,68 @@ defineSuite([ }); }); + it('renders based on classificationType' + webglMessage, function() { + var rectangle = Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0); + var polygonOptions = createPolygon(rectangle); + + var batchTable = new Cesium3DTileBatchTable(mockTileset, 1); + batchTable.update(mockTileset, scene.frameState); + + scene.primitives.add(globePrimitive); + scene.primitives.add(tilesetPrimitive); + + var center = ellipsoid.cartographicToCartesian(Rectangle.center(rectangle)); + polygons = scene.primitives.add(new Vector3DTilePolygons(combine(polygonOptions, { + minimumHeight : -10000.0, + maximumHeight : 10000.0, + center : center, + rectangle : rectangle, + boundingVolume : new BoundingSphere(center, 10000.0), + batchTable : batchTable, + batchIds : new Uint32Array([0]), + isCartographic : true + }))); + return loadPolygons(polygons).then(function() { + scene.camera.setView({ + destination : rectangle + }); + + polygons.classificationType = ClassificationType.CESIUM_3D_TILE; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expect(scene).toRender([255, 255, 255, 255]); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expect(scene).toRender([255, 0, 0, 255]); + + polygons.classificationType = ClassificationType.TERRAIN; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expect(scene).toRender([255, 0, 0, 255]); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expect(scene).toRender([255, 255, 255, 255]); + + polygons.classificationType = ClassificationType.BOTH; + globePrimitive.show = false; + tilesetPrimitive.show = true; + expect(scene).toRender([255, 255, 255, 255]); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expect(scene).toRender([255, 255, 255, 255]); + + globePrimitive.show = true; + tilesetPrimitive.show = true; + }); + }); + it('picks polygons' + webglMessage, function() { var rectangle = Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0); var polygonOptions = createPolygon(rectangle); var batchTable = new Cesium3DTileBatchTable(mockTileset, 1); - scene.primitives.add(depthPrimitive); + scene.primitives.add(globePrimitive); var center = ellipsoid.cartographicToCartesian(Rectangle.center(rectangle)); polygons = scene.primitives.add(new Vector3DTilePolygons(combine(polygonOptions, { From e3a297c76b235d0eb05ce6670abb559eb4258a5d Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 19 Dec 2018 13:54:50 -0500 Subject: [PATCH 14/39] Test cleanup --- .../Scene/Batched3DModel3DTileContentClassificationSpec.js | 2 ++ Specs/Scene/ClassificationModelSpec.js | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js b/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js index b01865967a94..eceb751f6df5 100644 --- a/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js +++ b/Specs/Scene/Batched3DModel3DTileContentClassificationSpec.js @@ -173,6 +173,8 @@ defineSuite([ globePrimitive.show = true; tilesetPrimitive.show = false; Cesium3DTilesTester.expectRenderBlank(scene, tileset); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); diff --git a/Specs/Scene/ClassificationModelSpec.js b/Specs/Scene/ClassificationModelSpec.js index 07bc16aa5f44..45fc1f661e3d 100644 --- a/Specs/Scene/ClassificationModelSpec.js +++ b/Specs/Scene/ClassificationModelSpec.js @@ -226,6 +226,8 @@ defineSuite([ globePrimitive.show = true; tilesetPrimitive.show = false; expectRenderBlank(scene, model); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); @@ -237,6 +239,8 @@ defineSuite([ globePrimitive.show = true; tilesetPrimitive.show = false; expectRender(scene, model); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); @@ -248,6 +252,8 @@ defineSuite([ globePrimitive.show = true; tilesetPrimitive.show = false; expectRender(scene, model); + globePrimitive.show = true; + tilesetPrimitive.show = true; }); }); From 33db32a4b34263ddf59f7a52db477e5b88b07516 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 19 Dec 2018 13:58:40 -0500 Subject: [PATCH 15/39] Updated CHANGES.md --- CHANGES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index f8589d5e9e38..30522b7c7b57 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,12 @@ Change Log ========== +### 1.45 - 2019-02-01 + +##### Fixes :wrench: +* Fixed an issue where classification primitives with the `CESIUM_3D_TILE` classification type would render on terrain. [#6568](https://github.com/AnalyticalGraphicsInc/cesium/issues/6568) +* Fixed an issue where 3D Tiles would show through the globe. [#6867](https://github.com/AnalyticalGraphicsInc/cesium/issues/6867) + ### 1.53 - 2019-01-02 ##### Fixes :wrench: From e610befe33e02abc4d76fe1e8af426133ae01cd5 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 19 Dec 2018 22:15:15 -0500 Subject: [PATCH 16/39] Temp --- Source/Renderer/AutomaticUniforms.js | 5 ++-- Source/Scene/GlobeDepth.js | 35 ++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Source/Renderer/AutomaticUniforms.js b/Source/Renderer/AutomaticUniforms.js index 988f6dbe5c9e..4fc2ed0d50e1 100644 --- a/Source/Renderer/AutomaticUniforms.js +++ b/Source/Renderer/AutomaticUniforms.js @@ -167,8 +167,9 @@ define([ }), /** - * An automatic GLSL uniform representing the depth after - * only the globe has been rendered and packed into an RGBA texture. + * An automatic GLSL uniform representing the depth of the scene + * after the globe pass and then updated after the 3D Tiles pass. + * The depth is packed into an RGBA texture. * * @private * diff --git a/Source/Scene/GlobeDepth.js b/Source/Scene/GlobeDepth.js index 7076b8ae5f2d..163413c08f47 100644 --- a/Source/Scene/GlobeDepth.js +++ b/Source/Scene/GlobeDepth.js @@ -16,7 +16,10 @@ define([ '../Renderer/TextureMinificationFilter', '../Shaders/PostProcessStages/DepthViewPacked', '../Shaders/PostProcessStages/PassThrough', - '../Shaders/PostProcessStages/PassThroughDepth' + '../Shaders/PostProcessStages/PassThroughDepth', + './StencilConstants', + './StencilFunction', + './StencilOperation' ], function( BoundingRectangle, Color, @@ -35,7 +38,10 @@ define([ TextureMinificationFilter, DepthViewPacked, PassThrough, - PassThroughDepth) { + PassThroughDepth, + StencilConstants, + StencilFunction, + StencilOperation) { 'use strict'; /** @@ -52,6 +58,7 @@ define([ this._clearColorCommand = undefined; this._copyColorCommand = undefined; this._copyDepthCommand = undefined; + this._updateDepthCommand = undefined; this._viewport = new BoundingRectangle(); this._rs = undefined; @@ -223,6 +230,26 @@ define([ }); } + if (!defined(globeDepth._updateDepthCommand)) { + globeDepth._updateDepthCommand = context.createViewportQuadCommand(PassThroughDepth, { + owner : globeDepth, + renderState : RenderState.fromCache({ + stencilTest : { + enabled : true, + frontFunction : StencilFunction.EQUAL, + frontOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }, + backFunction : StencilFunction.NEVER, + reference : StencilConstants.CESIUM_3D_TILE_MASK, + mask : StencilConstants.CESIUM_3D_TILE_MASK + } + }) + }); + } + globeDepth._copyDepthCommand.renderState = globeDepth._rs; globeDepth._copyColorCommand.renderState = globeDepth._rs; @@ -259,6 +286,10 @@ define([ } }; + GlobeDepth.prototype.updateDepth = function(context, passState) { + if (defined(this._copyDepthCommand + }; + GlobeDepth.prototype.executeCopyColor = function(context, passState) { if (defined(this._copyColorCommand)) { this._copyColorCommand.execute(context, passState); From bb1e49c7ef53811a9f7c3a7b0a030480e4ba7f4d Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 20 Dec 2018 10:38:12 -0500 Subject: [PATCH 17/39] Update GlobeDepth after 3D Tiles pass --- Source/Scene/GlobeDepth.js | 135 +++++++++++++++++++++++++++++-------- Source/Scene/Scene.js | 10 ++- 2 files changed, 117 insertions(+), 28 deletions(-) diff --git a/Source/Scene/GlobeDepth.js b/Source/Scene/GlobeDepth.js index 163413c08f47..188e07450832 100644 --- a/Source/Scene/GlobeDepth.js +++ b/Source/Scene/GlobeDepth.js @@ -51,23 +51,29 @@ define([ this._colorTexture = undefined; this._depthStencilTexture = undefined; this._globeDepthTexture = undefined; + this._tempGlobeDepthTexture = undefined; this.framebuffer = undefined; this._copyDepthFramebuffer = undefined; + this._tempCopyDepthFramebuffer = undefined; + this._updateDepthFramebuffer = undefined; this._clearColorCommand = undefined; this._copyColorCommand = undefined; this._copyDepthCommand = undefined; + this._tempCopyDepthCommand = undefined; this._updateDepthCommand = undefined; this._viewport = new BoundingRectangle(); this._rs = undefined; + this._rsUpdate = undefined; this._useScissorTest = false; this._scissorRectangle = undefined; this._useLogDepth = undefined; this._useHdr = undefined; + this._clearGlobeDepth = false; this._debugGlobeDepthViewportCommand = undefined; } @@ -111,14 +117,17 @@ define([ globeDepth._colorTexture = globeDepth._colorTexture && !globeDepth._colorTexture.isDestroyed() && globeDepth._colorTexture.destroy(); globeDepth._depthStencilTexture = globeDepth._depthStencilTexture && !globeDepth._depthStencilTexture.isDestroyed() && globeDepth._depthStencilTexture.destroy(); globeDepth._globeDepthTexture = globeDepth._globeDepthTexture && !globeDepth._globeDepthTexture.isDestroyed() && globeDepth._globeDepthTexture.destroy(); + globeDepth._tempGlobeDepthTexture = globeDepth._tempGlobeDepthTexture && !globeDepth._tempGlobeDepthTexture.isDestroyed() && globeDepth._tempGlobeDepthTexture.destroy(); } function destroyFramebuffers(globeDepth) { globeDepth.framebuffer = globeDepth.framebuffer && !globeDepth.framebuffer.isDestroyed() && globeDepth.framebuffer.destroy(); globeDepth._copyDepthFramebuffer = globeDepth._copyDepthFramebuffer && !globeDepth._copyDepthFramebuffer.isDestroyed() && globeDepth._copyDepthFramebuffer.destroy(); + globeDepth._tempCopyDepthFramebuffer = globeDepth._tempCopyDepthFramebuffer && !globeDepth._tempCopyDepthFramebuffer.isDestroyed() && globeDepth._tempCopyDepthFramebuffer.destroy(); + globeDepth._updateDepthFramebuffer = globeDepth._updateDepthFramebuffer && !globeDepth._updateDepthFramebuffer.isDestroyed() && globeDepth._updateDepthFramebuffer.destroy(); } - function createTextures(globeDepth, context, width, height, hdr) { + function createTextures(globeDepth, context, width, height, hdr, clearGlobeDepth) { var pixelDatatype = hdr ? (context.halfFloatingPointTexture ? PixelDatatype.HALF_FLOAT : PixelDatatype.FLOAT) : PixelDatatype.UNSIGNED_BYTE; globeDepth._colorTexture = new Texture({ context : context, @@ -155,9 +164,25 @@ define([ magnificationFilter : TextureMagnificationFilter.NEAREST }) }); + + if (clearGlobeDepth) { + globeDepth._tempGlobeDepthTexture = new Texture({ + context : context, + width : width, + height : height, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : new Sampler({ + wrapS : TextureWrap.CLAMP_TO_EDGE, + wrapT : TextureWrap.CLAMP_TO_EDGE, + minificationFilter : TextureMinificationFilter.NEAREST, + magnificationFilter : TextureMagnificationFilter.NEAREST + }) + }); + } } - function createFramebuffers(globeDepth, context) { + function createFramebuffers(globeDepth, context, clearGlobeDepth) { globeDepth.framebuffer = new Framebuffer({ context : context, colorTextures : [globeDepth._colorTexture], @@ -170,16 +195,31 @@ define([ colorTextures : [globeDepth._globeDepthTexture], destroyAttachments : false }); + + if (clearGlobeDepth) { + globeDepth._tempCopyDepthFramebuffer = new Framebuffer({ + context : context, + colorTextures : [globeDepth._tempGlobeDepthTexture], + destroyAttachments : false + }); + globeDepth._updateDepthFramebuffer = new Framebuffer({ + context : context, + colorTextures : [globeDepth._globeDepthTexture], + depthStencilTexture : globeDepth._depthStencilTexture, + destroyAttachments : false + }); + } } - function updateFramebuffers(globeDepth, context, width, height, hdr) { + function updateFramebuffers(globeDepth, context, width, height, hdr, clearGlobeDepth) { var colorTexture = globeDepth._colorTexture; var textureChanged = !defined(colorTexture) || colorTexture.width !== width || colorTexture.height !== height || hdr !== globeDepth._useHdr; - if (!defined(globeDepth.framebuffer) || textureChanged) { + var clearGlobeDepthChanged = clearGlobeDepth !== globeDepth._clearGlobeDepth; + if (!defined(globeDepth.framebuffer) || textureChanged || clearGlobeDepthChanged) { destroyTextures(globeDepth); destroyFramebuffers(globeDepth); - createTextures(globeDepth, context, width, height, hdr); - createFramebuffers(globeDepth, context); + createTextures(globeDepth, context, width, height, hdr, clearGlobeDepth); + createFramebuffers(globeDepth, context, clearGlobeDepth); } } @@ -204,6 +244,26 @@ define([ rectangle : globeDepth._scissorRectangle } }); + // Copy packed depth only if the 3D Tiles bit is set + globeDepth._rsUpdate = RenderState.fromCache({ + viewport : globeDepth._viewport, + scissorTest : { + enabled : globeDepth._useScissorTest, + rectangle : globeDepth._scissorRectangle + }, + stencilTest : { + enabled : true, + frontFunction : StencilFunction.EQUAL, + frontOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }, + backFunction : StencilFunction.NEVER, + reference : StencilConstants.CESIUM_3D_TILE_MASK, + mask : StencilConstants.CESIUM_3D_TILE_MASK + } + }); } if (!defined(globeDepth._copyDepthCommand)) { @@ -218,6 +278,7 @@ define([ } globeDepth._copyDepthCommand.framebuffer = globeDepth._copyDepthFramebuffer; + globeDepth._copyDepthCommand.renderState = globeDepth._rs; if (!defined(globeDepth._copyColorCommand)) { globeDepth._copyColorCommand = context.createViewportQuadCommand(PassThrough, { @@ -230,28 +291,33 @@ define([ }); } + if (!defined(globeDepth._tempCopyDepthCommand)) { + globeDepth._tempCopyDepthCommand = context.createViewportQuadCommand(PassThroughDepth, { + uniformMap : { + u_depthTexture : function() { + return globeDepth._depthStencilTexture; + } + }, + owner : globeDepth + }); + } + + globeDepth._tempCopyDepthCommand.framebuffer = globeDepth._tempCopyDepthFramebuffer; + globeDepth._tempCopyDepthCommand.renderState = globeDepth._rs; + if (!defined(globeDepth._updateDepthCommand)) { - globeDepth._updateDepthCommand = context.createViewportQuadCommand(PassThroughDepth, { - owner : globeDepth, - renderState : RenderState.fromCache({ - stencilTest : { - enabled : true, - frontFunction : StencilFunction.EQUAL, - frontOperation : { - fail : StencilOperation.KEEP, - zFail : StencilOperation.KEEP, - zPass : StencilOperation.KEEP - }, - backFunction : StencilFunction.NEVER, - reference : StencilConstants.CESIUM_3D_TILE_MASK, - mask : StencilConstants.CESIUM_3D_TILE_MASK + globeDepth._updateDepthCommand = context.createViewportQuadCommand(PassThrough, { + uniformMap : { + colorTexture : function() { + return globeDepth._tempGlobeDepthTexture; } - }) + }, + owner : globeDepth }); } - globeDepth._copyDepthCommand.renderState = globeDepth._rs; - globeDepth._copyColorCommand.renderState = globeDepth._rs; + globeDepth._updateDepthCommand.framebuffer = globeDepth._updateDepthFramebuffer; + globeDepth._updateDepthCommand.renderState = globeDepth._rsUpdate; if (!defined(globeDepth._clearColorCommand)) { globeDepth._clearColorCommand = new ClearCommand({ @@ -268,15 +334,16 @@ define([ executeDebugGlobeDepth(this, context, passState, useLogDepth); }; - GlobeDepth.prototype.update = function(context, passState, viewport, hdr) { + GlobeDepth.prototype.update = function(context, passState, viewport, hdr, clearGlobeDepth) { var width = viewport.width; var height = viewport.height; - updateFramebuffers(this, context, width, height, hdr); + updateFramebuffers(this, context, width, height, hdr, clearGlobeDepth); updateCopyCommands(this, context, width, height, passState); context.uniformState.globeDepthTexture = undefined; this._useHdr = hdr; + this._clearGlobeDepth = clearGlobeDepth; }; GlobeDepth.prototype.executeCopyDepth = function(context, passState) { @@ -286,8 +353,22 @@ define([ } }; - GlobeDepth.prototype.updateDepth = function(context, passState) { - if (defined(this._copyDepthCommand + GlobeDepth.prototype.executeUpdateDepth = function(context, passState, clearGlobeDepth) { + if (clearGlobeDepth) { + // First copy the depth to a temporary globe depth texture, then update the + // main globe depth texture where the stencil bit for 3D Tiles is set. + // This preserves the original globe depth except where 3D Tiles is rendered. + if (defined(this._tempCopyDepthCommand) && defined(this._updateDepthCommand)) { + this._tempCopyDepthCommand.execute(context, passState); + this._updateDepthCommand.execute(context, passState); + } + return; + } + + // Fast path - the depth texture can be copied normally. + if (defined(this._copyDepthCommand)) { + this._copyDepthCommand.execute(context, passState); + } }; GlobeDepth.prototype.executeCopyColor = function(context, passState) { diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index 92823beab81b..95166c3bbf12 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -2243,6 +2243,10 @@ define([ executeCommand(commands[j], scene, context, passState); } + if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { + globeDepth.executeUpdateDepth(context, passState, clearGlobeDepth); + } + // Draw classifications. Modifies 3D Tiles color. us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION); commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION]; @@ -2296,6 +2300,10 @@ define([ executeCommand(commands[j], scene, context, passState); } + if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { + globeDepth.executeUpdateDepth(context, passState, clearGlobeDepth); + } + // Set stencil us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW); commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW]; @@ -2926,7 +2934,7 @@ define([ // Globe depth is copied for the pick pass to support picking batched geometries in GroundPrimitives. var useGlobeDepthFramebuffer = environmentState.useGlobeDepthFramebuffer = defined(view.globeDepth); if (useGlobeDepthFramebuffer) { - view.globeDepth.update(context, passState, view.viewport, scene._hdr); + view.globeDepth.update(context, passState, view.viewport, scene._hdr, environmentState.clearGlobeDepth); view.globeDepth.clear(context, passState, clearColor); } From dd45faa902ddf65d86f7f7ac23e6d8dd06d239ae Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 20 Dec 2018 11:59:37 -0500 Subject: [PATCH 18/39] Support ground primitive batches for all classification types --- Source/DataSources/GeometryVisualizer.js | 25 +++---- .../StaticGroundGeometryPerMaterialBatch.js | 10 +-- Source/Scene/GroundPrimitive.js | 8 +-- Specs/DataSources/GeometryVisualizerSpec.js | 66 ------------------- ...taticGroundGeometryPerMaterialBatchSpec.js | 14 ++-- 5 files changed, 23 insertions(+), 100 deletions(-) diff --git a/Source/DataSources/GeometryVisualizer.js b/Source/DataSources/GeometryVisualizer.js index 2f70c1eb260a..1ccbea669c13 100644 --- a/Source/DataSources/GeometryVisualizer.js +++ b/Source/DataSources/GeometryVisualizer.js @@ -173,27 +173,21 @@ define([ var groundColorBatches = new Array(numberOfClassificationTypes); var groundMaterialBatches = []; if (supportsMaterialsforEntitiesOnTerrain) { - // Culling, phong shading only supported for ClassificationType.TERRAIN at the moment because - // tileset depth information not yet available. - groundColorBatches[ClassificationType.TERRAIN] = new StaticGroundGeometryPerMaterialBatch(groundPrimitives, PerInstanceColorAppearance); for (i = 0; i < numberOfClassificationTypes; ++i) { - if (i !== ClassificationType.TERRAIN) { - groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); - } - } - groundMaterialBatches[0] = new StaticGroundGeometryPerMaterialBatch(groundPrimitives, MaterialAppearance); - this._groundTerrainMaterialBatch = groundMaterialBatches[0]; - } else { - for (i = 0; i < numberOfClassificationTypes; ++i) { - groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); + groundMaterialBatches.push(new StaticGroundGeometryPerMaterialBatch(groundPrimitives, i, MaterialAppearance)); } } + for (i = 0; i < numberOfClassificationTypes; ++i) { + groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); + } + this._groundColorBatches = groundColorBatches; + this._groundMaterialBatches = groundMaterialBatches; this._dynamicBatch = new DynamicGeometryBatch(primitives, groundPrimitives); - this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._groundColorBatches, groundMaterialBatches, this._dynamicBatch); + this._batches = this._outlineBatches.concat(this._closedColorBatches, this._closedMaterialBatches, this._openColorBatches, this._openMaterialBatches, this._groundColorBatches, this._groundMaterialBatches, this._dynamicBatch); this._subscriptions = new AssociativeArray(); this._updaterSets = new AssociativeArray(); @@ -414,10 +408,7 @@ define([ this._groundColorBatches[classificationType].add(time, updater); } else { // If unsupported, updater will not be on terrain. - // If the updater has a material, ignore input ClassificationType for now and only classify terrain. - // Culling, phong shading only supported for ClassificationType.TERRAIN at the moment because - // tileset depth information not yet available. - this._groundTerrainMaterialBatch.add(time, updater); + this._groundMaterialBatches[classificationType].add(time, updater); } } else if (updater.isClosed) { if (updater.fillMaterialProperty instanceof ColorMaterialProperty) { diff --git a/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js b/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js index c4fe25feea59..b761892ae5ff 100644 --- a/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js +++ b/Source/DataSources/StaticGroundGeometryPerMaterialBatch.js @@ -34,8 +34,9 @@ define([ var defaultDistanceDisplayCondition = new DistanceDisplayCondition(); // Encapsulates a Primitive and all the entities that it represents. - function Batch(primitives, appearanceType, materialProperty, usingSphericalTextureCoordinates, zIndex) { + function Batch(primitives, classificationType, appearanceType, materialProperty, usingSphericalTextureCoordinates, zIndex) { this.primitives = primitives; // scene level primitive collection + this.classificationType = classificationType; this.appearanceType = appearanceType; this.materialProperty = materialProperty; this.updaters = new AssociativeArray(); @@ -142,7 +143,7 @@ define([ material : this.material // translucent and closed properties overridden }), - classificationType : ClassificationType.TERRAIN + classificationType : this.classificationType }); primitives.add(primitive, this.zIndex); @@ -266,9 +267,10 @@ define([ /** * @private */ - function StaticGroundGeometryPerMaterialBatch(primitives, appearanceType) { + function StaticGroundGeometryPerMaterialBatch(primitives, classificationType, appearanceType) { this._items = []; this._primitives = primitives; + this._classificationType = classificationType; this._appearanceType = appearanceType; } @@ -293,7 +295,7 @@ define([ } } // If a compatible batch wasn't found, create a new batch. - var batch = new Batch(this._primitives, this._appearanceType, updater.fillMaterialProperty, usingSphericalTextureCoordinates, zIndex); + var batch = new Batch(this._primitives, this._classificationType, this._appearanceType, updater.fillMaterialProperty, usingSphericalTextureCoordinates, zIndex); batch.add(time, updater, geometryInstance); items.push(batch); }; diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 3efbaac2bd55..0837060bdc98 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -659,12 +659,6 @@ define([ return; } - //>>includeStart('debug', pragmas.debug); - if (this.classificationType !== ClassificationType.TERRAIN && !(this.appearance instanceof PerInstanceColorAppearance)) { - throw new DeveloperError('GroundPrimitives with Materials can only classify ClassificationType.TERRAIN at this time.'); - } - //>>includeEnd('debug'); - var that = this; var primitiveOptions = this._classificationPrimitiveOptions; @@ -712,7 +706,7 @@ define([ this._minHeight = this._minTerrainHeight * exaggeration; this._maxHeight = this._maxTerrainHeight * exaggeration; - var useFragmentCulling = GroundPrimitive._supportsMaterials(frameState.context) && this.classificationType === ClassificationType.TERRAIN; + var useFragmentCulling = GroundPrimitive._supportsMaterials(frameState.context); this._useFragmentCulling = useFragmentCulling; if (useFragmentCulling) { diff --git a/Specs/DataSources/GeometryVisualizerSpec.js b/Specs/DataSources/GeometryVisualizerSpec.js index f0fd0c5e426c..70692ad75c32 100644 --- a/Specs/DataSources/GeometryVisualizerSpec.js +++ b/Specs/DataSources/GeometryVisualizerSpec.js @@ -911,72 +911,6 @@ defineSuite([ }); }); - it('batches ground entities by identical color if ClassificationType is not TERRAIN', function() { - var entities = new EntityCollection(); - var visualizer = new GeometryVisualizer(scene, entities, scene.primitives, scene.groundPrimitives); - - var blueColor = Color.BLUE.withAlpha(0.5); - entities.add({ - position : new Cartesian3(1, 2, 3), - ellipse : { - semiMajorAxis : 2, - semiMinorAxis : 1, - material : blueColor, - classificationType : ClassificationType.BOTH - } - }); - - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { - expect(scene.groundPrimitives.length).toEqual(1); - - entities.add({ - position : new Cartesian3(12, 34, 45), - ellipse : { - semiMajorAxis : 2, - semiMinorAxis : 1, - material : blueColor, - classificationType : ClassificationType.BOTH - } - }); - - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); - }).then(function() { - expect(scene.groundPrimitives.length).toEqual(1); - - entities.add({ - position : new Cartesian3(123, 456, 789), - ellipse : { - semiMajorAxis : 2, - semiMinorAxis : 1, - material : Color.BLUE.withAlpha(0.6), - classificationType : ClassificationType.BOTH - } - }); - - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); - }).then(function() { - expect(scene.groundPrimitives.length).toEqual(2); - - entities.removeAll(); - visualizer.destroy(); - }); - }); - it('batches ground entities classifying terrain by material if ground entity materials is supported', function() { if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { return; diff --git a/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js b/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js index e90c7393f5b9..4562e01a394e 100644 --- a/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js +++ b/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js @@ -20,6 +20,7 @@ defineSuite([ 'DataSources/PolylineGeometryUpdater', 'DataSources/PolylineGraphics', 'DataSources/TimeIntervalCollectionProperty', + 'Scene/ClassificationType', 'Scene/GroundPrimitive', 'Scene/MaterialAppearance', 'Scene/PolylineColorAppearance', @@ -48,6 +49,7 @@ defineSuite([ PolylineGeometryUpdater, PolylineGraphics, TimeIntervalCollectionProperty, + ClassificationType, GroundPrimitive, MaterialAppearance, PolylineColorAppearance, @@ -80,7 +82,7 @@ defineSuite([ return; } - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); var ellipse = new EllipseGraphics(); ellipse.semiMajorAxis = new ConstantProperty(2); @@ -151,7 +153,7 @@ defineSuite([ } }); - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); var updater = new EllipseGeometryUpdater(entity, scene); batch.add(validTime, updater); @@ -184,7 +186,7 @@ defineSuite([ return; } - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); function buildEntity(x, y, z) { var material = new GridMaterialProperty({ @@ -258,7 +260,7 @@ defineSuite([ return; } - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); var ellipse = new EllipseGraphics(); ellipse.semiMajorAxis = new ConstantProperty(2); @@ -303,7 +305,7 @@ defineSuite([ return; } - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); var entity = new Entity({ position : new Cartesian3(1234, 5678, 9101112), ellipse : { @@ -349,7 +351,7 @@ defineSuite([ return; } - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); function buildEntity(x, y, z) { var material = new GridMaterialProperty({ From 6a50bbc423f44cd8b979992a95c0907d3adb3010 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 20 Dec 2018 12:08:57 -0500 Subject: [PATCH 19/39] Update Classification Types demo --- .../gallery/Classification Types.html | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Apps/Sandcastle/gallery/Classification Types.html b/Apps/Sandcastle/gallery/Classification Types.html index f818b0c10787..c1d6c8d3d4b4 100644 --- a/Apps/Sandcastle/gallery/Classification Types.html +++ b/Apps/Sandcastle/gallery/Classification Types.html @@ -48,7 +48,7 @@ } }); -var options = [{ +var classificationOptions = [{ text : 'Classify Both', onselect : function() { entity.polygon.classificationType = Cesium.ClassificationType.BOTH; @@ -64,7 +64,21 @@ entity.polygon.classificationType = Cesium.ClassificationType.CESIUM_3D_TILE; } }]; -Sandcastle.addToolbarMenu(options); + +var materialOptions = [{ + text : 'Red Material', + onselect : function() { + entity.polygon.material = Cesium.Color.RED.withAlpha(0.5); + } +}, { + text : 'Textured Material', + onselect : function() { + entity.polygon.material = '../images/Cesium_Logo_Color.jpg'; + } +}]; + +Sandcastle.addToolbarMenu(classificationOptions); +Sandcastle.addToolbarMenu(materialOptions); //Sandcastle_End Sandcastle.finishedLoading(); } From eeea2bef896fdb79524ae3f6e92d37dd400a3bd2 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 20 Dec 2018 12:12:14 -0500 Subject: [PATCH 20/39] Change classification defaults to BOTH everywhere --- Source/DataSources/GeometryUpdater.js | 2 +- Source/Scene/GroundPrimitive.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/DataSources/GeometryUpdater.js b/Source/DataSources/GeometryUpdater.js index 6783a2c650cf..d33253d5d28c 100644 --- a/Source/DataSources/GeometryUpdater.js +++ b/Source/DataSources/GeometryUpdater.js @@ -43,7 +43,7 @@ define([ var defaultOutlineColor = new ConstantProperty(Color.BLACK); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); - var defaultClassificationType = new ConstantProperty(ClassificationType.TERRAIN); + var defaultClassificationType = new ConstantProperty(ClassificationType.BOTH); /** * An abstract class for updating geometry entites. diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 0837060bdc98..09e94b02845a 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -105,7 +105,7 @@ define([ * @param {Boolean} [options.releaseGeometryInstances=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory. * @param {Boolean} [options.allowPicking=true] When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved. * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready. If false initializeTerrainHeights() must be called first. - * @param {ClassificationType} [options.classificationType=ClassificationType.TERRAIN] Determines whether terrain, 3D Tiles or both will be classified. + * @param {ClassificationType} [options.classificationType=ClassificationType.BOTH] Determines whether terrain, 3D Tiles or both will be classified. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown. * @param {Boolean} [options.debugShowShadowVolume=false] For debugging only. Determines if the shadow volume for each geometry in the primitive is drawn. Must be true on * creation for the volumes to be created before the geometry is released or options.releaseGeometryInstance must be false. @@ -214,9 +214,9 @@ define([ * * @type {ClassificationType} * - * @default ClassificationType.TERRAIN + * @default ClassificationType.BOTH */ - this.classificationType = defaultValue(options.classificationType, ClassificationType.TERRAIN); + this.classificationType = defaultValue(options.classificationType, ClassificationType.BOTH); /** * This property is for debugging only; it is not for production use nor is it optimized. *

From 572102fe7d051a78cd9c74d847e457bc2e884570 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 20 Dec 2018 13:15:12 -0500 Subject: [PATCH 21/39] Fix tests --- Source/DataSources/GeometryVisualizer.js | 9 +- Specs/DataSources/GeometryVisualizerSpec.js | 15 +- Specs/Scene/GroundPrimitiveSpec.js | 156 +++++++------------- 3 files changed, 69 insertions(+), 111 deletions(-) diff --git a/Source/DataSources/GeometryVisualizer.js b/Source/DataSources/GeometryVisualizer.js index 1ccbea669c13..7e1ee6c4cf29 100644 --- a/Source/DataSources/GeometryVisualizer.js +++ b/Source/DataSources/GeometryVisualizer.js @@ -175,11 +175,12 @@ define([ if (supportsMaterialsforEntitiesOnTerrain) { for (i = 0; i < numberOfClassificationTypes; ++i) { groundMaterialBatches.push(new StaticGroundGeometryPerMaterialBatch(groundPrimitives, i, MaterialAppearance)); + groundColorBatches[i] = new StaticGroundGeometryPerMaterialBatch(groundPrimitives, i, PerInstanceColorAppearance); + } + } else { + for (i = 0; i < numberOfClassificationTypes; ++i) { + groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); } - } - - for (i = 0; i < numberOfClassificationTypes; ++i) { - groundColorBatches[i] = new StaticGroundGeometryColorBatch(groundPrimitives, i); } this._groundColorBatches = groundColorBatches; diff --git a/Specs/DataSources/GeometryVisualizerSpec.js b/Specs/DataSources/GeometryVisualizerSpec.js index 70692ad75c32..489d7694c243 100644 --- a/Specs/DataSources/GeometryVisualizerSpec.js +++ b/Specs/DataSources/GeometryVisualizerSpec.js @@ -911,7 +911,7 @@ defineSuite([ }); }); - it('batches ground entities classifying terrain by material if ground entity materials is supported', function() { + it('batches ground entities by material if ground entity materials is supported', function() { if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { return; } @@ -986,13 +986,22 @@ defineSuite([ } }); + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }); + }).then(function() { + expect(scene.groundPrimitives.length).toEqual(2); + entities.add({ position : Cartesian3.fromDegrees(-12, -34), ellipse : { semiMajorAxis : 2, semiMinorAxis : 1, material : './Data/Images/White.png', - classificationType : ClassificationType.BOTH // expect to render as ClassificationType.TERRAIN + classificationType : ClassificationType.CESIUM_3D_TILE } }); @@ -1003,7 +1012,7 @@ defineSuite([ return isUpdated; }); }).then(function() { - expect(scene.groundPrimitives.length).toEqual(2); + expect(scene.groundPrimitives.length).toEqual(3); entities.removeAll(); visualizer.destroy(); diff --git a/Specs/Scene/GroundPrimitiveSpec.js b/Specs/Scene/GroundPrimitiveSpec.js index 65e592793db1..6c8e3d22c64c 100644 --- a/Specs/Scene/GroundPrimitiveSpec.js +++ b/Specs/Scene/GroundPrimitiveSpec.js @@ -374,13 +374,15 @@ defineSuite([ expect(frameState.commandList.length).toEqual(0); }); - function expectRender(color) { - expect(scene).toRender(color); + function expectRender(scene, color) { + expect(scene).toRenderAndCall(function(rgba) { + expect(arraySlice(rgba, 0, 4)).toEqual(color); + }); } - function expectRenderBlank() { + function expectRenderBlank(scene) { expect(scene).toRenderAndCall(function(rgba) { - expect(rgba).not.toEqual([0, 0, 0, 255]); + expect(arraySlice(rgba)).not.toEqual([0, 0, 0, 255]); expect(rgba[0]).toEqual(0); }); } @@ -391,33 +393,33 @@ defineSuite([ scene.primitives.add(globePrimitive); scene.primitives.add(tilesetPrimitive); - expectRenderBlank(); + expectRenderBlank(scene); scene.groundPrimitives.add(primitive); primitive.classificationType = ClassificationType.BOTH; globePrimitive.show = false; tilesetPrimitive.show = true; - expectRender(color); + expectRender(scene, color); globePrimitive.show = true; tilesetPrimitive.show = false; - expectRender(color); + expectRender(scene, color); primitive.classificationType = ClassificationType.CESIUM_3D_TILE; globePrimitive.show = false; tilesetPrimitive.show = true; - expectRender(color); + expectRender(scene, color); globePrimitive.show = true; tilesetPrimitive.show = false; - expectRenderBlank(); + expectRenderBlank(scene); primitive.classificationType = ClassificationType.TERRAIN; globePrimitive.show = false; tilesetPrimitive.show = true; - expectRenderBlank(); + expectRenderBlank(scene); globePrimitive.show = true; tilesetPrimitive.show = false; - expectRender(color); + expectRender(scene, color); globePrimitive.show = true; tilesetPrimitive.show = true; @@ -565,17 +567,41 @@ defineSuite([ largeScene.camera.setView({destination : destination}); var largeSceneGlobePrimitive = new MockPrimitive(largeSceneReusableGlobePrimitive, Pass.GLOBE); + var largeSceneTilesetPrimitive = new MockPrimitive(largeSceneReusableTilesetPrimitive, Pass.CESIUM_3D_TILE); largeScene.primitives.add(largeSceneGlobePrimitive); - expect(largeScene).toRenderAndCall(function(rgba) { - expect(arraySlice(rgba, 0, 4)).not.toEqual([0, 0, 0, 255]); - expect(rgba[0]).toEqual(0); - }); + largeScene.primitives.add(largeSceneTilesetPrimitive); + + expectRenderBlank(largeScene); largeScene.groundPrimitives.add(groundPrimitive); - expect(largeScene).toRenderAndCall(function(rgba) { - expect(arraySlice(rgba, 0, 4)).toEqual(expectedColor); - }); + + groundPrimitive.classificationType = ClassificationType.BOTH; + largeSceneGlobePrimitive.show = false; + largeSceneTilesetPrimitive.show = true; + expectRender(largeScene, expectedColor); + globePrimitive.show = true; + tilesetPrimitive.show = false; + expectRender(largeScene, expectedColor); + + groundPrimitive.classificationType = ClassificationType.CESIUM_3D_TILE; + largeSceneGlobePrimitive.show = false; + largeSceneTilesetPrimitive.show = true; + expectRender(largeScene, expectedColor); + globePrimitive.show = true; + largeSceneTilesetPrimitive.show = false; + expectRenderBlank(largeScene); + + groundPrimitive.classificationType = ClassificationType.TERRAIN; + largeSceneGlobePrimitive.show = false; + largeSceneTilesetPrimitive.show = true; + expectRenderBlank(largeScene); + largeSceneGlobePrimitive.show = true; + largeSceneTilesetPrimitive.show = false; + expectRender(largeScene, expectedColor); + + largeSceneGlobePrimitive.show = true; + largeSceneTilesetPrimitive.show = true; } it('renders batched instances', function() { @@ -613,7 +639,7 @@ defineSuite([ verifyLargerScene(batchedPrimitive, [0, 255, 255, 255], rectangle); }); - it('renders small GeometryInstances with texture classifying terrain', function() { + it('renders small GeometryInstances with texture', function() { if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { return; } @@ -638,14 +664,13 @@ defineSuite([ flat : true, material : whiteImageMaterial }), - asynchronous : false, - classificationType : ClassificationType.TERRAIN + asynchronous : false }); verifyLargerScene(smallRectanglePrimitive, [255, 255, 255, 255], smallRectangle); }); - it('renders large GeometryInstances with texture classifying terrain', function() { + it('renders large GeometryInstances with texture', function() { if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { return; } @@ -670,14 +695,13 @@ defineSuite([ flat : true, material : whiteImageMaterial }), - asynchronous : false, - classificationType : ClassificationType.TERRAIN + asynchronous : false }); verifyLargerScene(largeRectanglePrimitive, [255, 255, 255, 255], largeRectangle); }); - it('renders GeometryInstances with texture classifying terrain across the IDL', function() { + it('renders GeometryInstances with texture across the IDL', function() { if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { return; } @@ -699,46 +723,11 @@ defineSuite([ flat : true, material : whiteImageMaterial }), - asynchronous : false, - classificationType : ClassificationType.TERRAIN + asynchronous : false }); verifyLargerScene(largeRectanglePrimitive, [255, 255, 255, 255], largeRectangle); }); - - it('update throws with texture and ClassificationType that is not TERRAIN', function() { - if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { - return; - } - - var whiteImageMaterial = Material.fromType(Material.DiffuseMapType); - whiteImageMaterial.uniforms.image = './Data/Images/White.png'; - - var radians = CesiumMath.toRadians(0.1); - var west = rectangle.west; - var south = rectangle.south; - var smallRectangle = new Rectangle(west, south, west + radians, south + radians); - var smallRectanglePrimitive = new GroundPrimitive({ - geometryInstances : new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : smallRectangle - }), - id : 'smallRectangle' - }), - appearance : new EllipsoidSurfaceAppearance({ - aboveGround : false, - flat : true, - material : whiteImageMaterial - }), - asynchronous : false, - classificationType : ClassificationType.BOTH - }); - - expect(function() { - verifyLargerScene(smallRectanglePrimitive, [255, 255, 255, 255], smallRectangle); - }).toThrowDeveloperError(); - }); }); it('renders with invert classification and an opaque color', function() { @@ -753,8 +742,7 @@ defineSuite([ primitive = new GroundPrimitive({ geometryInstances : rectangleInstance, - asynchronous : false, - classificationType : ClassificationType.BOTH + asynchronous : false }); scene.camera.setView({ destination : rectangle }); @@ -793,8 +781,7 @@ defineSuite([ primitive = new GroundPrimitive({ geometryInstances : rectangleInstance, - asynchronous : false, - classificationType : ClassificationType.BOTH + asynchronous : false }); scene.camera.setView({ destination : rectangle }); @@ -1213,45 +1200,6 @@ defineSuite([ }).toThrowDeveloperError(); }); - it('update throws when batched instance colors are different and ClassificationType is not TERRAIN', function() { - if (!GroundPrimitive.isSupported(scene) || !GroundPrimitive.supportsMaterials(scene)) { - return; - } - - var rectColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 1.0, 1.0, 1.0)); - var rectangleInstance1 = new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : new Rectangle(rectangle.west, rectangle.south, rectangle.east, (rectangle.north + rectangle.south) * 0.5) - }), - id : 'rectangle1', - attributes : { - color : rectColorAttribute - } - }); - rectColorAttribute = ColorGeometryInstanceAttribute.fromColor(new Color(1.0, 1.0, 0.0, 1.0)); - var rectangleInstance2 = new GeometryInstance({ - geometry : new RectangleGeometry({ - ellipsoid : ellipsoid, - rectangle : new Rectangle(rectangle.west, (rectangle.north + rectangle.south) * 0.5, rectangle.east, rectangle.north) - }), - id : 'rectangle2', - attributes : { - color : rectColorAttribute - } - }); - - primitive = new GroundPrimitive({ - geometryInstances : [rectangleInstance1, rectangleInstance2], - asynchronous : false, - classificationType : ClassificationType.BOTH - }); - - expect(function() { - verifyGroundPrimitiveRender(primitive, rectColorAttribute.value); - }).toThrowDeveloperError(); - }); - it('update throws when one batched instance color is undefined', function() { if (!GroundPrimitive.isSupported(scene)) { return; From adf2881cf4b1ad66d44b41ed22d408a07785eff9 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 20 Dec 2018 13:36:33 -0500 Subject: [PATCH 22/39] Optimization to not update depth or render CESUM_3D_TILE classification if there are no 3D Tiles commands --- Source/Scene/GlobeDepth.js | 88 ++++++++++++++++++--------------- Source/Scene/Scene.js | 22 +++++---- Specs/Scene/MultifrustumSpec.js | 2 +- 3 files changed, 60 insertions(+), 52 deletions(-) diff --git a/Source/Scene/GlobeDepth.js b/Source/Scene/GlobeDepth.js index 188e07450832..bcd9857d91b9 100644 --- a/Source/Scene/GlobeDepth.js +++ b/Source/Scene/GlobeDepth.js @@ -64,6 +64,8 @@ define([ this._tempCopyDepthCommand = undefined; this._updateDepthCommand = undefined; + this._requiresUpdateDepthResources = false; + this._viewport = new BoundingRectangle(); this._rs = undefined; this._rsUpdate = undefined; @@ -73,7 +75,6 @@ define([ this._useLogDepth = undefined; this._useHdr = undefined; - this._clearGlobeDepth = false; this._debugGlobeDepthViewportCommand = undefined; } @@ -127,7 +128,34 @@ define([ globeDepth._updateDepthFramebuffer = globeDepth._updateDepthFramebuffer && !globeDepth._updateDepthFramebuffer.isDestroyed() && globeDepth._updateDepthFramebuffer.destroy(); } - function createTextures(globeDepth, context, width, height, hdr, clearGlobeDepth) { + function createUpdateDepthResources(globeDepth, context, width, height) { + globeDepth._tempGlobeDepthTexture = new Texture({ + context : context, + width : width, + height : height, + pixelFormat : PixelFormat.RGBA, + pixelDatatype : PixelDatatype.UNSIGNED_BYTE, + sampler : new Sampler({ + wrapS : TextureWrap.CLAMP_TO_EDGE, + wrapT : TextureWrap.CLAMP_TO_EDGE, + minificationFilter : TextureMinificationFilter.NEAREST, + magnificationFilter : TextureMagnificationFilter.NEAREST + }) + }); + globeDepth._tempCopyDepthFramebuffer = new Framebuffer({ + context : context, + colorTextures : [globeDepth._tempGlobeDepthTexture], + destroyAttachments : false + }); + globeDepth._updateDepthFramebuffer = new Framebuffer({ + context : context, + colorTextures : [globeDepth._globeDepthTexture], + depthStencilTexture : globeDepth._depthStencilTexture, + destroyAttachments : false + }); + } + + function createTextures(globeDepth, context, width, height, hdr) { var pixelDatatype = hdr ? (context.halfFloatingPointTexture ? PixelDatatype.HALF_FLOAT : PixelDatatype.FLOAT) : PixelDatatype.UNSIGNED_BYTE; globeDepth._colorTexture = new Texture({ context : context, @@ -164,25 +192,9 @@ define([ magnificationFilter : TextureMagnificationFilter.NEAREST }) }); - - if (clearGlobeDepth) { - globeDepth._tempGlobeDepthTexture = new Texture({ - context : context, - width : width, - height : height, - pixelFormat : PixelFormat.RGBA, - pixelDatatype : PixelDatatype.UNSIGNED_BYTE, - sampler : new Sampler({ - wrapS : TextureWrap.CLAMP_TO_EDGE, - wrapT : TextureWrap.CLAMP_TO_EDGE, - minificationFilter : TextureMinificationFilter.NEAREST, - magnificationFilter : TextureMagnificationFilter.NEAREST - }) - }); - } } - function createFramebuffers(globeDepth, context, clearGlobeDepth) { + function createFramebuffers(globeDepth, context) { globeDepth.framebuffer = new Framebuffer({ context : context, colorTextures : [globeDepth._colorTexture], @@ -195,31 +207,19 @@ define([ colorTextures : [globeDepth._globeDepthTexture], destroyAttachments : false }); - - if (clearGlobeDepth) { - globeDepth._tempCopyDepthFramebuffer = new Framebuffer({ - context : context, - colorTextures : [globeDepth._tempGlobeDepthTexture], - destroyAttachments : false - }); - globeDepth._updateDepthFramebuffer = new Framebuffer({ - context : context, - colorTextures : [globeDepth._globeDepthTexture], - depthStencilTexture : globeDepth._depthStencilTexture, - destroyAttachments : false - }); - } } - function updateFramebuffers(globeDepth, context, width, height, hdr, clearGlobeDepth) { + function updateFramebuffers(globeDepth, context, width, height, hdr) { var colorTexture = globeDepth._colorTexture; var textureChanged = !defined(colorTexture) || colorTexture.width !== width || colorTexture.height !== height || hdr !== globeDepth._useHdr; - var clearGlobeDepthChanged = clearGlobeDepth !== globeDepth._clearGlobeDepth; - if (!defined(globeDepth.framebuffer) || textureChanged || clearGlobeDepthChanged) { + if (!defined(globeDepth.framebuffer) || textureChanged) { destroyTextures(globeDepth); destroyFramebuffers(globeDepth); - createTextures(globeDepth, context, width, height, hdr, clearGlobeDepth); - createFramebuffers(globeDepth, context, clearGlobeDepth); + createTextures(globeDepth, context, width, height, hdr); + createFramebuffers(globeDepth, context); + if (globeDepth._requiresUpdateDepthResources) { + createUpdateDepthResources(globeDepth, context, width, height); + } } } @@ -334,16 +334,15 @@ define([ executeDebugGlobeDepth(this, context, passState, useLogDepth); }; - GlobeDepth.prototype.update = function(context, passState, viewport, hdr, clearGlobeDepth) { + GlobeDepth.prototype.update = function(context, passState, viewport, hdr) { var width = viewport.width; var height = viewport.height; - updateFramebuffers(this, context, width, height, hdr, clearGlobeDepth); + updateFramebuffers(this, context, width, height, hdr); updateCopyCommands(this, context, width, height, passState); context.uniformState.globeDepthTexture = undefined; this._useHdr = hdr; - this._clearGlobeDepth = clearGlobeDepth; }; GlobeDepth.prototype.executeCopyDepth = function(context, passState) { @@ -358,7 +357,14 @@ define([ // First copy the depth to a temporary globe depth texture, then update the // main globe depth texture where the stencil bit for 3D Tiles is set. // This preserves the original globe depth except where 3D Tiles is rendered. + // The additional texture and framebuffer resources are created on demand. + this._requiresUpdateDepthResources = true; if (defined(this._tempCopyDepthCommand) && defined(this._updateDepthCommand)) { + if (!defined(this._updateDepthFramebuffer)) { + var width = this._globeDepthTexture.width; + var height = this._globeDepthTexture.height; + createUpdateDepthResources(this, context, width, height); + } this._tempCopyDepthCommand.execute(context, passState); this._updateDepthCommand.execute(context, passState); } diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index 95166c3bbf12..bb826571254a 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -2243,16 +2243,18 @@ define([ executeCommand(commands[j], scene, context, passState); } - if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { - globeDepth.executeUpdateDepth(context, passState, clearGlobeDepth); - } + if (length > 0) { + if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { + globeDepth.executeUpdateDepth(context, passState, clearGlobeDepth); + } - // Draw classifications. Modifies 3D Tiles color. - us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION); - commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION]; - length = frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION]; - for (j = 0; j < length; ++j) { - executeCommand(commands[j], scene, context, passState); + // Draw classifications. Modifies 3D Tiles color. + us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION); + commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION]; + length = frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION]; + for (j = 0; j < length; ++j) { + executeCommand(commands[j], scene, context, passState); + } } } else { // When the invert classification color is opaque: @@ -2934,7 +2936,7 @@ define([ // Globe depth is copied for the pick pass to support picking batched geometries in GroundPrimitives. var useGlobeDepthFramebuffer = environmentState.useGlobeDepthFramebuffer = defined(view.globeDepth); if (useGlobeDepthFramebuffer) { - view.globeDepth.update(context, passState, view.viewport, scene._hdr, environmentState.clearGlobeDepth); + view.globeDepth.update(context, passState, view.viewport, scene._hdr); view.globeDepth.clear(context, passState, clearColor); } diff --git a/Specs/Scene/MultifrustumSpec.js b/Specs/Scene/MultifrustumSpec.js index 692536eab401..8a89b7a66d99 100644 --- a/Specs/Scene/MultifrustumSpec.js +++ b/Specs/Scene/MultifrustumSpec.js @@ -218,7 +218,7 @@ defineSuite([ var found = false; var sources = billboardCall.object.shaderProgram.fragmentShaderSource.sources; for (var j = 0; j < sources.length; ++j) { - if (sources[i].indexOf('czm_Debug_main') !== -1) { + if (sources[j].indexOf('czm_Debug_main') !== -1) { found = true; break; } From 42cc67c4ae6584e0973f8cbef4ab9b4d9df1b732 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 20 Dec 2018 15:06:39 -0500 Subject: [PATCH 23/39] Doc updates --- Source/DataSources/Entity.js | 2 +- Source/DataSources/GroundGeometryUpdater.js | 70 ++++++++++----------- Source/Scene/ClassificationPrimitive.js | 3 +- Source/Scene/GroundPrimitive.js | 12 ++-- 4 files changed, 42 insertions(+), 45 deletions(-) diff --git a/Source/DataSources/Entity.js b/Source/DataSources/Entity.js index b5170a14fa46..f3b8eb4411ca 100644 --- a/Source/DataSources/Entity.js +++ b/Source/DataSources/Entity.js @@ -664,7 +664,7 @@ define([ }; /** - * Checks if the given Scene supports materials besides Color on Entities draped on terrain. + * Checks if the given Scene supports materials besides Color on Entities draped on terrain or 3D Tiles. * If this feature is not supported, Entities with non-color materials but no `height` will * instead be rendered as if height is 0. * diff --git a/Source/DataSources/GroundGeometryUpdater.js b/Source/DataSources/GroundGeometryUpdater.js index c7fd10b8fe43..97908b9f0228 100644 --- a/Source/DataSources/GroundGeometryUpdater.js +++ b/Source/DataSources/GroundGeometryUpdater.js @@ -1,39 +1,39 @@ define([ - '../Core/ApproximateTerrainHeights', - '../Core/Cartesian3', - '../Core/Check', - '../Core/defaultValue', - '../Core/defined', - '../Core/defineProperties', - '../Core/DeveloperError', - '../Core/GeometryOffsetAttribute', - '../Core/Iso8601', - '../Core/oneTimeWarning', - '../Scene/GroundPrimitive', - '../Scene/HeightReference', - './CallbackProperty', - './ConstantProperty', - './GeometryUpdater', - './Property', - './TerrainOffsetProperty' -], function( - ApproximateTerrainHeights, - Cartesian3, - Check, - defaultValue, - defined, - defineProperties, - DeveloperError, - GeometryOffsetAttribute, - Iso8601, - oneTimeWarning, - GroundPrimitive, - HeightReference, - CallbackProperty, - ConstantProperty, - GeometryUpdater, - Property, - TerrainOffsetProperty) { + '../Core/ApproximateTerrainHeights', + '../Core/Cartesian3', + '../Core/Check', + '../Core/defaultValue', + '../Core/defined', + '../Core/defineProperties', + '../Core/DeveloperError', + '../Core/GeometryOffsetAttribute', + '../Core/Iso8601', + '../Core/oneTimeWarning', + '../Scene/GroundPrimitive', + '../Scene/HeightReference', + './CallbackProperty', + './ConstantProperty', + './GeometryUpdater', + './Property', + './TerrainOffsetProperty' + ], function( + ApproximateTerrainHeights, + Cartesian3, + Check, + defaultValue, + defined, + defineProperties, + DeveloperError, + GeometryOffsetAttribute, + Iso8601, + oneTimeWarning, + GroundPrimitive, + HeightReference, + CallbackProperty, + ConstantProperty, + GeometryUpdater, + Property, + TerrainOffsetProperty) { 'use strict'; var defaultZIndex = new ConstantProperty(0); diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js index d2c1ca987238..d0dcc4695b7a 100644 --- a/Source/Scene/ClassificationPrimitive.js +++ b/Source/Scene/ClassificationPrimitive.js @@ -67,8 +67,7 @@ define([ * and match most of them and add a new geometry or appearance independently of each other. * Only {@link PerInstanceColorAppearance} with the same color across all instances is supported at this time when using * ClassificationPrimitive directly. - * For full {@link Appearance} support when classifying terrain use {@link GroundPrimitive} instead. - * + * For full {@link Appearance} support when classifying terrain or 3D Tiles use {@link GroundPrimitive} instead. *

*

* For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there diff --git a/Source/Scene/GroundPrimitive.js b/Source/Scene/GroundPrimitive.js index 09e94b02845a..dbeddae47721 100644 --- a/Source/Scene/GroundPrimitive.js +++ b/Source/Scene/GroundPrimitive.js @@ -67,22 +67,20 @@ define([ }; /** - * A ground primitive represents geometry draped over the terrain in the {@link Scene}. + * A ground primitive represents geometry draped over terrain or 3D Tiles in the {@link Scene}. *

* A primitive combines geometry instances with an {@link Appearance} that describes the full shading, including * {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement, * and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix * and match most of them and add a new geometry or appearance independently of each other. - * - * Only {@link PerInstanceColorAppearance} with the same color across all instances is supported at this time when - * classifying {@link ClassificationType}.CESIUM_3D_TILE and {@link ClassificationType}.BOTH. - * + *

+ *

* Support for the WEBGL_depth_texture extension is required to use GeometryInstances with different PerInstanceColors * or materials besides PerInstanceColorAppearance. - * + *

+ *

* Textured GroundPrimitives were designed for notional patterns and are not meant for precisely mapping * textures to terrain - for that use case, use {@link SingleTileImageryProvider}. - * *

*

* For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there From c17cf47aacca88228c8554662e5f6b95b2391bf7 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 20 Dec 2018 15:16:02 -0500 Subject: [PATCH 24/39] Update CHANGES.md --- CHANGES.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 30522b7c7b57..5d2532c5c69b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,11 +1,19 @@ Change Log ========== -### 1.45 - 2019-02-01 +### 1.54 - 2019-02-01 + +##### Additions :tada: + +* Added support for textured ground entities (entities with unspecified `height`) and `GroundPrimitives` on 3D Tiles. ##### Fixes :wrench: -* Fixed an issue where classification primitives with the `CESIUM_3D_TILE` classification type would render on terrain. [#6568](https://github.com/AnalyticalGraphicsInc/cesium/issues/6568) -* Fixed an issue where 3D Tiles would show through the globe. [#6867](https://github.com/AnalyticalGraphicsInc/cesium/issues/6867) +* Fixed an issue where classification primitives with the `CESIUM_3D_TILE` classification type would render on terrain. +* Fixed an issue where 3D Tiles would show through the globe. + +##### Breaking Changes :mega: +* Billboards with `HeightReference.CLAMP_TO_GROUND` are now clamped to both terrain and 3D Tiles. +* The default `classificationType` for `GroundPrimitive`, `CorridorGraphics`, `EllipseGraphics`, `PolygonGraphics` and `RectangleGraphics` is now `ClassificationType.BOTH`. ### 1.53 - 2019-01-02 From cea11caeac072398a828cea51c893d8fc141248c Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Fri, 21 Dec 2018 13:09:53 -0500 Subject: [PATCH 25/39] Fix for first frame after depthTestAgainstTerrain is disabled --- Source/Scene/GlobeDepth.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Scene/GlobeDepth.js b/Source/Scene/GlobeDepth.js index bcd9857d91b9..b79f4a644c68 100644 --- a/Source/Scene/GlobeDepth.js +++ b/Source/Scene/GlobeDepth.js @@ -359,11 +359,12 @@ define([ // This preserves the original globe depth except where 3D Tiles is rendered. // The additional texture and framebuffer resources are created on demand. this._requiresUpdateDepthResources = true; - if (defined(this._tempCopyDepthCommand) && defined(this._updateDepthCommand)) { + if (defined(this._updateDepthCommand)) { if (!defined(this._updateDepthFramebuffer)) { var width = this._globeDepthTexture.width; var height = this._globeDepthTexture.height; createUpdateDepthResources(this, context, width, height); + updateCopyCommands(this, context, width, height, passState); } this._tempCopyDepthCommand.execute(context, passState); this._updateDepthCommand.execute(context, passState); From 5e458c8077dee0568539ab45164ba7b755dc11fc Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Fri, 21 Dec 2018 17:34:58 -0500 Subject: [PATCH 26/39] GroundPolylinePrimitive on 3D Tiles --- Source/Core/GroundPolylineGeometry.js | 6 +- Source/Scene/ClassificationPrimitive.js | 2 - Source/Scene/GroundPolylinePrimitive.js | 153 ++++++++++++++++-------- 3 files changed, 103 insertions(+), 58 deletions(-) diff --git a/Source/Core/GroundPolylineGeometry.js b/Source/Core/GroundPolylineGeometry.js index 1c03744df648..c29e2748f5d7 100644 --- a/Source/Core/GroundPolylineGeometry.js +++ b/Source/Core/GroundPolylineGeometry.js @@ -70,7 +70,7 @@ define([ var WALL_INITIAL_MAX_HEIGHT = 1000.0; /** - * A description of a polyline on terrain. Only to be used with {@link GroundPolylinePrimitive}. + * A description of a polyline on terrain or 3D Tiles. Only to be used with {@link GroundPolylinePrimitive}. * * @alias GroundPolylineGeometry * @constructor @@ -159,7 +159,7 @@ define([ * Set the GroundPolylineGeometry's projection and ellipsoid. * Used by GroundPolylinePrimitive to signal scene information to the geometry for generating 2D attributes. * - * @param {GroundPolylineGeometry} groundPolylineGeometry GroundPolylinGeometry describing a polyline on terrain. + * @param {GroundPolylineGeometry} groundPolylineGeometry GroundPolylinGeometry describing a polyline on terrain or 3D Tiles. * @param {Projection} mapProjection A MapProjection used for projecting cartographic coordinates to 2D. * @private */ @@ -386,7 +386,7 @@ define([ var intersectionScratch = new Cartesian3(); /** * Computes shadow volumes for the ground polyline, consisting of its vertices, indices, and a bounding sphere. - * Vertices are "fat," packing all the data needed in each volume to describe a line on terrain. + * Vertices are "fat," packing all the data needed in each volume to describe a line on terrain or 3D Tiles. * Should not be called independent of {@link GroundPolylinePrimitive}. * * @param {GroundPolylineGeometry} groundPolylineGeometry diff --git a/Source/Scene/ClassificationPrimitive.js b/Source/Scene/ClassificationPrimitive.js index d0dcc4695b7a..764ee174c20a 100644 --- a/Source/Scene/ClassificationPrimitive.js +++ b/Source/Scene/ClassificationPrimitive.js @@ -766,7 +766,6 @@ define([ // Then derive from the 3D Tiles command derived2DCommand = DrawCommand.shallowClone(derivedCommand, derivedCommand.derivedCommands.appearance2D); derived2DCommand.shaderProgram = classificationPrimitive._spColor2D; - derived2DCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; derivedCommand.derivedCommands.appearance2D = derived2DCommand; } } @@ -908,7 +907,6 @@ define([ // Then derive from the 3D Tiles command derived2DCommand = DrawCommand.shallowClone(derivedCommand, derivedCommand.derivedCommands.pick2D); derived2DCommand.shaderProgram = classificationPrimitive._spPick2D; - derived2DCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; derivedCommand.derivedCommands.pick2D = derived2DCommand; } } diff --git a/Source/Scene/GroundPolylinePrimitive.js b/Source/Scene/GroundPolylinePrimitive.js index 7d052e567843..896aec902ed8 100644 --- a/Source/Scene/GroundPolylinePrimitive.js +++ b/Source/Scene/GroundPolylinePrimitive.js @@ -21,11 +21,15 @@ define([ '../Renderer/ShaderSource', '../ThirdParty/when', './BlendingState', + './ClassificationType', './CullFace', './PolylineColorAppearance', './PolylineMaterialAppearance', './Primitive', - './SceneMode' + './SceneMode', + './StencilConstants', + './StencilFunction', + './StencilOperation' ], function( ApproximateTerrainHeights, ComponentDatatype, @@ -49,18 +53,22 @@ define([ ShaderSource, when, BlendingState, + ClassificationType, CullFace, PolylineColorAppearance, PolylineMaterialAppearance, Primitive, - SceneMode) { + SceneMode, + StencilConstants, + StencilFunction, + StencilOperation) { 'use strict'; /** - * A GroundPolylinePrimitive represents a polyline draped over the terrain in the {@link Scene}. + * A GroundPolylinePrimitive represents a polyline draped over the terrain or 3D Tiles in the {@link Scene}. *

- * * Only to be used with GeometryInstances containing {@link GroundPolylineGeometry}. + *

* * @alias GroundPolylinePrimitive * @constructor @@ -73,6 +81,7 @@ define([ * @param {Boolean} [options.releaseGeometryInstances=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory. * @param {Boolean} [options.allowPicking=true] When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved. * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready. If false initializeTerrainHeights() must be called first. + * @param {ClassificationType} [options.classificationType=ClassificationType.BOTH] Determines whether terrain, 3D Tiles or both will be classified. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown. * @param {Boolean} [options.debugShowShadowVolume=false] For debugging only. Determines if the shadow volume for each geometry in the primitive is drawn. Must be true on creation to have effect. * @@ -168,6 +177,15 @@ define([ */ this.show = defaultValue(options.show, true); + /** + * Determines whether terrain, 3D Tiles or both will be classified. + * + * @type {ClassificationType} + * + * @default ClassificationType.BOTH + */ + this.classificationType = defaultValue(options.classificationType, ClassificationType.BOTH); + /** * This property is for debugging only; it is not for production use nor is it optimized. *

@@ -209,13 +227,8 @@ define([ this._sp2D = undefined; this._spMorph = undefined; - this._renderState = RenderState.fromCache({ - cull : { - enabled : true // prevent double-draw. Geometry is "inverted" (reversed winding order) so we're drawing backfaces. - }, - blending : BlendingState.ALPHA_BLEND, - depthMask : false - }); + this._renderState = getRenderState(false); + this._renderState3DTiles = getRenderState(true); this._renderStateMorph = RenderState.fromCache({ cull : { @@ -454,6 +467,33 @@ define([ groundPolylinePrimitive._spMorph = colorProgramMorph; } + function getRenderState(mask3DTiles) { + return RenderState.fromCache({ + cull : { + enabled : true // prevent double-draw. Geometry is "inverted" (reversed winding order) so we're drawing backfaces. + }, + blending : BlendingState.ALPHA_BLEND, + depthMask : false, + stencilTest : { + enabled : mask3DTiles, + frontFunction : StencilFunction.EQUAL, + frontOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }, + backFunction : StencilFunction.EQUAL, + backOperation : { + fail : StencilOperation.KEEP, + zFail : StencilOperation.KEEP, + zPass : StencilOperation.KEEP + }, + reference : StencilConstants.CESIUM_3D_TILE_MASK, + mask : StencilConstants.CESIUM_3D_TILE_MASK + } + }); + } + function createCommands(groundPolylinePrimitive, appearance, material, translucent, colorCommands, pickCommands) { var primitive = groundPolylinePrimitive._primitive; var length = primitive._va.length; @@ -462,16 +502,13 @@ define([ var isPolylineColorAppearance = appearance instanceof PolylineColorAppearance; - var i; - var command; var materialUniforms = isPolylineColorAppearance ? {} : material._uniforms; var uniformMap = primitive._batchTable.getUniformMapCallback()(materialUniforms); - var pass = Pass.TERRAIN_CLASSIFICATION; - for (i = 0; i < length; i++) { + for (var i = 0; i < length; i++) { var vertexArray = primitive._va[i]; - command = colorCommands[i]; + var command = colorCommands[i]; if (!defined(command)) { command = colorCommands[i] = new DrawCommand({ owner : groundPolylinePrimitive, @@ -483,37 +520,47 @@ define([ command.renderState = groundPolylinePrimitive._renderState; command.shaderProgram = groundPolylinePrimitive._sp; command.uniformMap = uniformMap; - command.pass = pass; + command.pass = Pass.TERRAIN_CLASSIFICATION; command.pickId = 'czm_batchTable_pickColor(v_endPlaneNormalEcAndBatchId.w)'; + var derivedTilesetCommand = DrawCommand.shallowClone(command, command.derivedCommands.tileset); + derivedTilesetCommand.renderState = groundPolylinePrimitive._renderState3DTiles; + derivedTilesetCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION; + command.derivedCommands.tileset = derivedTilesetCommand; + // derive for 2D - var derivedColorCommand = command.derivedCommands.color2D; - if (!defined(derivedColorCommand)) { - derivedColorCommand = DrawCommand.shallowClone(command); - command.derivedCommands.color2D = derivedColorCommand; - } - derivedColorCommand.vertexArray = vertexArray; - derivedColorCommand.renderState = groundPolylinePrimitive._renderState; - derivedColorCommand.shaderProgram = groundPolylinePrimitive._sp2D; - derivedColorCommand.uniformMap = uniformMap; - derivedColorCommand.pass = pass; - derivedColorCommand.pickId = 'czm_batchTable_pickColor(v_endPlaneNormalEcAndBatchId.w)'; + var derived2DCommand = DrawCommand.shallowClone(command, command.derivedCommands.color2D); + derived2DCommand.shaderProgram = groundPolylinePrimitive._sp2D; + command.derivedCommands.color2D = derived2DCommand; + + var derived2DTilesetCommand = DrawCommand.shallowClone(command, derivedTilesetCommand.derivedCommands.color2D); + derived2DTilesetCommand.shaderProgram = groundPolylinePrimitive._sp2D; + derivedTilesetCommand.derivedCommands.color2D = derived2DTilesetCommand; // derive for Morph - derivedColorCommand = command.derivedCommands.colorMorph; - if (!defined(derivedColorCommand)) { - derivedColorCommand = DrawCommand.shallowClone(command); - command.derivedCommands.colorMorph = derivedColorCommand; - } - derivedColorCommand.vertexArray = vertexArray; - derivedColorCommand.renderState = groundPolylinePrimitive._renderStateMorph; - derivedColorCommand.shaderProgram = groundPolylinePrimitive._spMorph; - derivedColorCommand.uniformMap = uniformMap; - derivedColorCommand.pass = pass; - derivedColorCommand.pickId = 'czm_batchTable_pickColor(v_batchId)'; + var derivedMorphCommand = DrawCommand.shallowClone(command, command.derivedCommands.colorMorph); + derivedMorphCommand.renderState = groundPolylinePrimitive._renderStateMorph; + derivedMorphCommand.shaderProgram = groundPolylinePrimitive._spMorph; + derivedMorphCommand.pickId = 'czm_batchTable_pickColor(v_batchId)'; + command.derivedCommands.colorMorph = derivedMorphCommand; } } + function updateAndQueueCommand(groundPolylinePrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume) { + // Use derived appearance command for morph and 2D + if (frameState.mode === SceneMode.MORPHING && command.shaderProgram !== groundPolylinePrimitive._spMorph) { + command = command.derivedCommands.colorMorph; + } else if (frameState.mode !== SceneMode.SCENE3D && command.shaderProgram !== groundPolylinePrimitive._sp2D) { + command = command.derivedCommands.color2D; + } + command.modelMatrix = modelMatrix; + command.boundingVolume = boundingVolume; + command.cull = cull; + command.debugShowBoundingVolume = debugShowBoundingVolume; + + frameState.commandList.push(command); + } + function updateAndQueueCommands(groundPolylinePrimitive, frameState, colorCommands, pickCommands, modelMatrix, cull, debugShowBoundingVolume) { var primitive = groundPolylinePrimitive._primitive; @@ -530,25 +577,25 @@ define([ boundingSpheres = primitive._boundingSphereMorph; } - var commandList = frameState.commandList; + var morphing = frameState.mode === SceneMode.MORPHING; + var classificationType = groundPolylinePrimitive.classificationType; + var queueTerrainCommands = (classificationType !== ClassificationType.CESIUM_3D_TILE); + var queue3DTilesCommands = (classificationType !== ClassificationType.TERRAIN) && !morphing; + + var command; var passes = frameState.passes; if (passes.render || (passes.pick && primitive.allowPicking)) { var colorLength = colorCommands.length; - for (var j = 0; j < colorLength; ++j) { - var colorCommand = colorCommands[j]; - // Use derived appearance command for morph and 2D - if (frameState.mode === SceneMode.MORPHING && colorCommand.shaderProgram !== groundPolylinePrimitive._spMorph) { - colorCommand = colorCommand.derivedCommands.colorMorph; - } else if (frameState.mode !== SceneMode.SCENE3D && colorCommand.shaderProgram !== groundPolylinePrimitive._sp2D) { - colorCommand = colorCommand.derivedCommands.color2D; + var boundingVolume = boundingSpheres[j]; + if (queueTerrainCommands) { + command = colorCommands[j]; + updateAndQueueCommand(groundPolylinePrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume); + } + if (queue3DTilesCommands) { + command = colorCommands[j].derivedCommands.tileset; + updateAndQueueCommand(groundPolylinePrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume); } - colorCommand.modelMatrix = modelMatrix; - colorCommand.boundingVolume = boundingSpheres[j]; - colorCommand.cull = cull; - colorCommand.debugShowBoundingVolume = debugShowBoundingVolume; - - commandList.push(colorCommand); } } } From b1e01ef9f601e1fffb2af25d435f354c231d24ab Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Sat, 22 Dec 2018 13:52:12 -0500 Subject: [PATCH 27/39] Add support in entity layer --- Source/DataSources/CorridorGraphics.js | 3 +- Source/DataSources/EllipseGraphics.js | 5 +- Source/DataSources/Entity.js | 2 +- Source/DataSources/PolygonGraphics.js | 3 +- Source/DataSources/PolylineGeometryUpdater.js | 20 ++- Source/DataSources/PolylineGraphics.js | 15 +- Source/DataSources/PolylineVisualizer.js | 19 ++- Source/DataSources/RectangleGraphics.js | 3 +- .../StaticGroundPolylinePerMaterialBatch.js | 11 +- Specs/DataSources/PolylineGraphicsSpec.js | 14 ++ Specs/DataSources/PolylineVisualizerSpec.js | 160 +++++++++++++++++- ...taticGroundPolylinePerMaterialBatchSpec.js | 20 ++- 12 files changed, 247 insertions(+), 28 deletions(-) diff --git a/Source/DataSources/CorridorGraphics.js b/Source/DataSources/CorridorGraphics.js index 268f4e7da314..5de15e0b003c 100644 --- a/Source/DataSources/CorridorGraphics.js +++ b/Source/DataSources/CorridorGraphics.js @@ -41,6 +41,7 @@ define([ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the distance between each latitude and longitude. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the corridor casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this corridor will be displayed. + * @param {Property} [options.classificationType=ClassificationType.BOTH] A Property specifying whether this corridor will classify terrain, 3D Tiles, or both when on the ground. * @param {ConstantProperty} [options.zIndex] A Property specifying the zIndex of the corridor, used for ordering. Only has an effect if height and extrudedHeight are undefined, and if the corridor is static. * * @see Entity @@ -232,7 +233,7 @@ define([ * Gets or sets the {@link ClassificationType} Property specifying whether this corridor will classify terrain, 3D Tiles, or both when on the ground. * @memberof CorridorGraphics.prototype * @type {Property} - * @default ClassificationType.TERRAIN + * @default ClassificationType.BOTH */ classificationType : createPropertyDescriptor('classificationType'), diff --git a/Source/DataSources/EllipseGraphics.js b/Source/DataSources/EllipseGraphics.js index c120ffc691c1..d909defbabb6 100644 --- a/Source/DataSources/EllipseGraphics.js +++ b/Source/DataSources/EllipseGraphics.js @@ -44,7 +44,8 @@ define([ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between points on the ellipse. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the ellipse casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this ellipse will be displayed. - * @param {ConstantProperty} [options.zIndex=0] A property specifying the zIndex of the Ellipse. Used for ordering ground geometry. Only has an effect if the ellipse is constant and neither height or exturdedHeight are specified. + * @param {Property} [options.classificationType=ClassificationType.BOTH] A Property specifying whether this ellipse will classify terrain, 3D Tiles, or both when on the ground. + @param {ConstantProperty} [options.zIndex=0] A property specifying the zIndex of the Ellipse. Used for ordering ground geometry. Only has an effect if the ellipse is constant and neither height or exturdedHeight are specified. * * @demo {@link https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Circles and Ellipses.html|Cesium Sandcastle Circles and Ellipses Demo} */ @@ -254,7 +255,7 @@ define([ * Gets or sets the {@link ClassificationType} Property specifying whether this ellipse will classify terrain, 3D Tiles, or both when on the ground. * @memberof EllipseGraphics.prototype * @type {Property} - * @default ClassificationType.TERRAIN + * @default ClassificationType.BOTH */ classificationType : createPropertyDescriptor('classificationType'), diff --git a/Source/DataSources/Entity.js b/Source/DataSources/Entity.js index f3b8eb4411ca..12479c976706 100644 --- a/Source/DataSources/Entity.js +++ b/Source/DataSources/Entity.js @@ -676,7 +676,7 @@ define([ }; /** - * Checks if the given Scene supports polylines clamped to the ground.. + * Checks if the given Scene supports polylines clamped to terrain or 3D Tiles. * If this feature is not supported, Entities with PolylineGraphics will be rendered with vertices at * the provided heights and using the `followSurface` parameter instead of clamped to the ground. * diff --git a/Source/DataSources/PolygonGraphics.js b/Source/DataSources/PolygonGraphics.js index 5eb968df4d59..c7ca77ad1258 100644 --- a/Source/DataSources/PolygonGraphics.js +++ b/Source/DataSources/PolygonGraphics.js @@ -43,6 +43,7 @@ define([ * @param {Boolean} [options.closeBottom=true] When false, leaves off the bottom of an extruded polygon open. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the polygon casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this polygon will be displayed. + * @param {Property} [options.classificationType=ClassificationType.BOTH] A Property specifying whether this ellipse will classify terrain, 3D Tiles, or both when on the ground. * @param {ConstantProperty} [options.zIndex=0] A property specifying the zIndex used for ordering ground geometry. Only has an effect if the polygon is constant and neither height or extrudedHeight are specified. * * @see Entity @@ -255,7 +256,7 @@ define([ * Gets or sets the {@link ClassificationType} Property specifying whether this polygon will classify terrain, 3D Tiles, or both when on the ground. * @memberof PolygonGraphics.prototype * @type {Property} - * @default ClassificationType.TERRAIN + * @default ClassificationType.BOTH */ classificationType : createPropertyDescriptor('classificationType'), diff --git a/Source/DataSources/PolylineGeometryUpdater.js b/Source/DataSources/PolylineGeometryUpdater.js index 87e1258e9005..8cc63def39b1 100644 --- a/Source/DataSources/PolylineGeometryUpdater.js +++ b/Source/DataSources/PolylineGeometryUpdater.js @@ -18,6 +18,7 @@ define([ '../Core/PolylinePipeline', '../Core/ShowGeometryInstanceAttribute', '../DataSources/Entity', + '../Scene/ClassificationType', '../Scene/GroundPolylinePrimitive', '../Scene/PolylineCollection', '../Scene/PolylineColorAppearance', @@ -48,6 +49,7 @@ define([ PolylinePipeline, ShowGeometryInstanceAttribute, Entity, + ClassificationType, GroundPolylinePrimitive, PolylineCollection, PolylineColorAppearance, @@ -70,6 +72,7 @@ define([ var defaultShow = new ConstantProperty(true); var defaultShadows = new ConstantProperty(ShadowMode.DISABLED); var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); + var defaultClassificationType = new ConstantProperty(ClassificationType.BOTH); function GeometryOptions() { this.vertexFormat = undefined; @@ -113,6 +116,7 @@ define([ this._materialProperty = undefined; this._shadowsProperty = undefined; this._distanceDisplayConditionProperty = undefined; + this._classificationTypeProperty = undefined; this._depthFailMaterialProperty = undefined; this._geometryOptions = new GeometryOptions(); this._groundGeometryOptions = new GroundGeometryOptions(); @@ -252,6 +256,18 @@ define([ return this._distanceDisplayConditionProperty; } }, + /** + * Gets or sets the {@link ClassificationType} Property specifying if this geometry will classify terrain, 3D Tiles, or both when on the ground. + * @memberof PolylineGeometryUpdater.prototype + * + * @type {Property} + * @readonly + */ + classificationTypeProperty : { + get : function() { + return this._classificationTypeProperty; + } + }, /** * Gets a value indicating if the geometry is time-varying. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater} @@ -473,6 +489,7 @@ define([ this._showProperty = defaultValue(show, defaultShow); this._shadowsProperty = defaultValue(polyline.shadows, defaultShadows); this._distanceDisplayConditionProperty = defaultValue(polyline.distanceDisplayCondition, defaultDistanceDisplayCondition); + this._classificationTypeProperty = defaultValue(polyline.classificationType, defaultClassificationType); this._fillEnabled = true; this._zIndex = defaultValue(zIndex, defaultZIndex); @@ -493,7 +510,7 @@ define([ var positions = positionsProperty.getValue(Iso8601.MINIMUM_VALUE, geometryOptions.positions); //Because of the way we currently handle reference properties, - //we can't automatically assume the positions are always valid. + //we can't automatically assume the positions are always valid. if (!defined(positions) || positions.length < 2) { if (this._fillEnabled) { this._fillEnabled = false; @@ -635,6 +652,7 @@ define([ this._groundPolylinePrimitive = groundPrimitives.add(new GroundPolylinePrimitive({ geometryInstances : geometryUpdater.createFillGeometryInstance(time), appearance : appearance, + classificationType : geometryUpdater.classificationTypeProperty.getValue(time), asynchronous : false }), Property.getValueOrUndefined(geometryUpdater.zIndex, time)); diff --git a/Source/DataSources/PolylineGraphics.js b/Source/DataSources/PolylineGraphics.js index 3700d18ec149..9a79779ca4e5 100644 --- a/Source/DataSources/PolylineGraphics.js +++ b/Source/DataSources/PolylineGraphics.js @@ -31,10 +31,11 @@ define([ * @param {Property} [options.width=1.0] A numeric Property specifying the width in pixels. * @param {Property} [options.show=true] A boolean Property specifying the visibility of the polyline. * @param {MaterialProperty} [options.material=Color.WHITE] A Property specifying the material used to draw the polyline. - * @param {MaterialProperty} [options.depthFailMaterial] A property specifiying the material used to draw the polyline when it is below the terrain. + * @param {MaterialProperty} [options.depthFailMaterial] A property specifying the material used to draw the polyline when it is below the terrain. * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude if followSurface is true. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the polyline casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this polyline will be displayed. + * @param {Property} [options.classificationType=ClassificationType.BOTH] A Property specifying whether this polyline will classify terrain, 3D Tiles, or both when on the ground. * @param {Property} [options.zIndex=0] A Property specifying the zIndex used for ordering ground geometry. Only has an effect if `clampToGround` is true and polylines on terrain is supported. * * @see Entity @@ -62,6 +63,8 @@ define([ this._shadowsSubscription = undefined; this._distanceDisplayCondition = undefined; this._distanceDisplayConditionSubscription = undefined; + this._classificationType = undefined; + this._classificationTypeSubscription = undefined; this._zIndex = undefined; this._zIndexSubscription = undefined; @@ -170,6 +173,14 @@ define([ */ distanceDisplayCondition : createPropertyDescriptor('distanceDisplayCondition'), + /** + * Gets or sets the {@link ClassificationType} Property specifying whether this polyline will classify terrain, 3D Tiles, or both when on the ground. + * @memberof PolylineGraphics.prototype + * @type {Property} + * @default ClassificationType.BOTH + */ + classificationType : createPropertyDescriptor('classificationType'), + /** * Gets or sets the zIndex Property specifying the ordering of the polyline. Only has an effect if `clampToGround` is true and polylines on terrain is supported. * @memberof RectangleGraphics.prototype @@ -199,6 +210,7 @@ define([ result.granularity = this.granularity; result.shadows = this.shadows; result.distanceDisplayCondition = this.distanceDisplayCondition; + result.classificationType = this.classificationType; result.zIndex = this.zIndex; return result; @@ -227,6 +239,7 @@ define([ this.granularity = defaultValue(this.granularity, source.granularity); this.shadows = defaultValue(this.shadows, source.shadows); this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); + this.classificationType = defaultValue(this.classificationType, source.classificationType); this.zIndex = defaultValue(this.zIndex, source.zIndex); }; diff --git a/Source/DataSources/PolylineVisualizer.js b/Source/DataSources/PolylineVisualizer.js index 7bf86fc489ae..a8c7b9d7925a 100644 --- a/Source/DataSources/PolylineVisualizer.js +++ b/Source/DataSources/PolylineVisualizer.js @@ -5,6 +5,7 @@ define([ '../Core/defaultValue', '../Core/defined', '../Core/destroyObject', + '../Scene/ClassificationType', '../Scene/PolylineColorAppearance', '../Scene/PolylineMaterialAppearance', '../Scene/ShadowMode', @@ -22,6 +23,7 @@ define([ defaultValue, defined, destroyObject, + ClassificationType, PolylineColorAppearance, PolylineMaterialAppearance, ShadowMode, @@ -52,7 +54,8 @@ define([ } if (updater.clampToGround && updater.fillEnabled) { // Also checks for support - that._groundBatch.add(time, updater); + var classificationType = updater.classificationTypeProperty.getValue(time); + that._groundBatches[classificationType].add(time, updater); return; } @@ -106,11 +109,12 @@ define([ this._removedObjects = new AssociativeArray(); this._changedObjects = new AssociativeArray(); + var i; var numberOfShadowModes = ShadowMode.NUMBER_OF_SHADOW_MODES; this._colorBatches = new Array(numberOfShadowModes * 3); this._materialBatches = new Array(numberOfShadowModes * 3); - for (var i = 0; i < numberOfShadowModes; ++i) { + for (i = 0; i < numberOfShadowModes; ++i) { this._colorBatches[i] = new StaticGeometryColorBatch(primitives, PolylineColorAppearance, undefined, false, i); // no depth fail appearance this._materialBatches[i] = new StaticGeometryPerMaterialBatch(primitives, PolylineMaterialAppearance, undefined, false, i); @@ -122,10 +126,15 @@ define([ } this._dynamicBatch = new DynamicGeometryBatch(primitives, groundPrimitives); - // Only available for terrain classification - this._groundBatch = new StaticGroundPolylinePerMaterialBatch(groundPrimitives); - this._batches = this._colorBatches.concat(this._materialBatches, this._dynamicBatch, this._groundBatch); + var numberOfClassificationTypes = ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES; + this._groundBatches = new Array(numberOfClassificationTypes); + + for (i = 0; i < numberOfClassificationTypes; ++i) { + this._groundBatches[i] = new StaticGroundPolylinePerMaterialBatch(groundPrimitives, i); + } + + this._batches = this._colorBatches.concat(this._materialBatches, this._dynamicBatch, this._groundBatches); this._subscriptions = new AssociativeArray(); this._updaters = new AssociativeArray(); diff --git a/Source/DataSources/RectangleGraphics.js b/Source/DataSources/RectangleGraphics.js index 9840679d75d0..0a7405c195a9 100644 --- a/Source/DataSources/RectangleGraphics.js +++ b/Source/DataSources/RectangleGraphics.js @@ -41,6 +41,7 @@ define([ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between points on the rectangle. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the rectangle casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this rectangle will be displayed. + * @param {Property} [options.classificationType=ClassificationType.BOTH] A Property specifying whether this rectangle will classify terrain, 3D Tiles, or both when on the ground. * @param {Property} [options.zIndex=0] A Property specifying the zIndex used for ordering ground geometry. Only has an effect if the rectangle is constant and neither height or extrudedHeight are specified. * * @see Entity @@ -234,7 +235,7 @@ define([ * Gets or sets the {@link ClassificationType} Property specifying whether this rectangle will classify terrain, 3D Tiles, or both when on the ground. * @memberof RectangleGraphics.prototype * @type {Property} - * @default ClassificationType.TERRAIN + * @default ClassificationType.BOTH */ classificationType : createPropertyDescriptor('classificationType'), diff --git a/Source/DataSources/StaticGroundPolylinePerMaterialBatch.js b/Source/DataSources/StaticGroundPolylinePerMaterialBatch.js index 5770e15b8183..399348c4c529 100644 --- a/Source/DataSources/StaticGroundPolylinePerMaterialBatch.js +++ b/Source/DataSources/StaticGroundPolylinePerMaterialBatch.js @@ -37,7 +37,7 @@ define([ var defaultDistanceDisplayCondition = new DistanceDisplayCondition(); // Encapsulates a Primitive and all the entities that it represents. - function Batch(orderedGroundPrimitives, materialProperty, zIndex, asynchronous) { + function Batch(orderedGroundPrimitives, classificationType, materialProperty, zIndex, asynchronous) { var appearanceType; if (materialProperty instanceof ColorMaterialProperty) { appearanceType = PolylineColorAppearance; @@ -46,6 +46,7 @@ define([ } this.orderedGroundPrimitives = orderedGroundPrimitives; // scene level primitive collection + this.classificationType = classificationType; this.appearanceType = appearanceType; this.materialProperty = materialProperty; this.updaters = new AssociativeArray(); @@ -139,7 +140,8 @@ define([ show : false, asynchronous : this._asynchronous, geometryInstances : geometries, - appearance : new this.appearanceType() + appearance : new this.appearanceType(), + classificationType : this.classificationType }); if (this.appearanceType === PolylineMaterialAppearance) { @@ -278,9 +280,10 @@ define([ /** * @private */ - function StaticGroundPolylinePerMaterialBatch(orderedGroundPrimitives, asynchronous) { + function StaticGroundPolylinePerMaterialBatch(orderedGroundPrimitives, classificationType, asynchronous) { this._items = []; this._orderedGroundPrimitives = orderedGroundPrimitives; + this._classificationType = classificationType; this._asynchronous = defaultValue(asynchronous, true); } @@ -299,7 +302,7 @@ define([ } } // If a compatible batch wasn't found, create a new batch. - var batch = new Batch(this._orderedGroundPrimitives, updater.fillMaterialProperty, zIndex, this._asynchronous); + var batch = new Batch(this._orderedGroundPrimitives, this._classificationType, updater.fillMaterialProperty, zIndex, this._asynchronous); batch.add(time, updater, geometryInstance); items.push(batch); }; diff --git a/Specs/DataSources/PolylineGraphicsSpec.js b/Specs/DataSources/PolylineGraphicsSpec.js index 97a69c5a8a19..b44bb4244dfe 100644 --- a/Specs/DataSources/PolylineGraphicsSpec.js +++ b/Specs/DataSources/PolylineGraphicsSpec.js @@ -4,6 +4,7 @@ defineSuite([ 'Core/DistanceDisplayCondition', 'DataSources/ColorMaterialProperty', 'DataSources/ConstantProperty', + 'Scene/ClassificationType', 'Scene/ShadowMode', 'Specs/testDefinitionChanged', 'Specs/testMaterialDefinitionChanged' @@ -13,6 +14,7 @@ defineSuite([ DistanceDisplayCondition, ColorMaterialProperty, ConstantProperty, + ClassificationType, ShadowMode, testDefinitionChanged, testMaterialDefinitionChanged) { @@ -30,6 +32,7 @@ defineSuite([ granularity : 2, shadows : ShadowMode.DISABLED, distanceDisplayCondition : new DistanceDisplayCondition(), + classificationType : ClassificationType.TERRAIN, zIndex : 0 }; @@ -44,6 +47,7 @@ defineSuite([ expect(polyline.granularity).toBeInstanceOf(ConstantProperty); expect(polyline.shadows).toBeInstanceOf(ConstantProperty); expect(polyline.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); + expect(polyline.classificationType).toBeInstanceOf(ConstantProperty); expect(polyline.zIndex).toBeInstanceOf(ConstantProperty); expect(polyline.material.color.getValue()).toEqual(options.material); @@ -56,6 +60,7 @@ defineSuite([ expect(polyline.granularity.getValue()).toEqual(options.granularity); expect(polyline.shadows.getValue()).toEqual(options.shadows); expect(polyline.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); + expect(polyline.classificationType.getValue()).toEqual(options.classificationType); expect(polyline.zIndex.getValue()).toEqual(options.zIndex); }); @@ -71,6 +76,7 @@ defineSuite([ source.granularity = new ConstantProperty(); source.shadows = new ConstantProperty(ShadowMode.ENABLED); source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); + source.classificationType = new ConstantProperty(ClassificationType.TERRAIN); source.zIndex = new ConstantProperty(); var target = new PolylineGraphics(); @@ -85,6 +91,7 @@ defineSuite([ expect(target.granularity).toBe(source.granularity); expect(target.shadows).toBe(source.shadows); expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); + expect(target.classificationType).toBe(source.classificationType); expect(target.zIndex).toBe(source.zIndex); }); @@ -100,6 +107,7 @@ defineSuite([ source.granularity = new ConstantProperty(); source.shadows = new ConstantProperty(); source.distanceDisplayCondition = new ConstantProperty(); + source.classificationType = new ConstantProperty(); source.zIndex = new ConstantProperty(); var color = new ColorMaterialProperty(); @@ -112,6 +120,7 @@ defineSuite([ var granularity = new ConstantProperty(); var shadows = new ConstantProperty(); var distanceDisplayCondition = new ConstantProperty(); + var classificationType = new ConstantProperty(); var zIndex = new ConstantProperty(); var target = new PolylineGraphics(); @@ -125,6 +134,7 @@ defineSuite([ target.granularity = granularity; target.shadows = shadows; target.distanceDisplayCondition = distanceDisplayCondition; + target.classificationType = classificationType; target.zIndex = zIndex; target.merge(source); @@ -138,6 +148,7 @@ defineSuite([ expect(target.granularity).toBe(granularity); expect(target.shadows).toBe(shadows); expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); + expect(target.classificationType).toBe(classificationType); expect(target.zIndex).toBe(zIndex); }); @@ -153,6 +164,7 @@ defineSuite([ source.granularity = new ConstantProperty(); source.shadows = new ConstantProperty(); source.distanceDisplayCondition = new ConstantProperty(); + source.classificationType = new ConstantProperty(); source.zIndex = new ConstantProperty(); var result = source.clone(); @@ -166,6 +178,7 @@ defineSuite([ expect(result.granularity).toBe(source.granularity); expect(result.shadows).toBe(source.shadows); expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); + expect(result.classificationType).toBe(source.classificationType); expect(result.zIndex).toBe(source.zIndex); }); @@ -188,6 +201,7 @@ defineSuite([ testDefinitionChanged(property, 'granularity', 2, 1); testDefinitionChanged(property, 'shadows', ShadowMode.ENABLED, ShadowMode.DISABLED); testDefinitionChanged(property, 'distanceDisplayCondition', new DistanceDisplayCondition(), new DistanceDisplayCondition(10.0, 20.0)); + testDefinitionChanged(property, 'classificationType', ClassificationType.TERRAIN); testDefinitionChanged(property, 'zIndex', 20, 5); }); }); diff --git a/Specs/DataSources/PolylineVisualizerSpec.js b/Specs/DataSources/PolylineVisualizerSpec.js index 34722cf0a608..26dd30e51bcc 100644 --- a/Specs/DataSources/PolylineVisualizerSpec.js +++ b/Specs/DataSources/PolylineVisualizerSpec.js @@ -16,6 +16,7 @@ defineSuite([ 'DataSources/EntityCollection', 'DataSources/PolylineArrowMaterialProperty', 'DataSources/PolylineGraphics', + 'Scene/ClassificationType', 'Scene/PolylineColorAppearance', 'Scene/PolylineMaterialAppearance', 'Scene/ShadowMode', @@ -40,6 +41,7 @@ defineSuite([ EntityCollection, PolylineArrowMaterialProperty, PolylineGraphics, + ClassificationType, PolylineColorAppearance, PolylineMaterialAppearance, ShadowMode, @@ -158,7 +160,7 @@ defineSuite([ } var objects = new EntityCollection(); - var visualizer = new PolylineVisualizer(scene, objects, scene.groundPrimitives); + var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); @@ -415,6 +417,54 @@ defineSuite([ }); }); + function createAndRemoveGeometryWithClassificationType(classificationType) { + var objects = new EntityCollection(); + var visualizer = new PolylineVisualizer(scene, objects); + + var polyline = new PolylineGraphics(); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.material = new ColorMaterialProperty(); + polyline.classificationType = new ConstantProperty(classificationType); + polyline.clampToGround = true; + + var entity = new Entity(); + entity.polyline = polyline; + objects.add(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }).then(function() { + var primitive = scene.groundPrimitives.get(0); + expect(primitive.classificationType).toBe(classificationType); + + objects.remove(entity); + + return pollToPromise(function() { + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + return scene.primitives.length === 0; + }).then(function(){ + visualizer.destroy(); + }); + }); + } + + it('Creates and removes geometry classifying terrain', function() { + return createAndRemoveGeometryWithClassificationType(ClassificationType.TERRAIN); + }); + + it('Creates and removes geometry classifying 3D Tiles', function() { + return createAndRemoveGeometryWithClassificationType(ClassificationType.CESIUM_3D_TILE); + }); + + it('Creates and removes geometry classifying both terrain and 3D Tiles', function() { + return createAndRemoveGeometryWithClassificationType(ClassificationType.BOTH); + }); + it('Correctly handles geometry changing batches', function() { var objects = new EntityCollection(); var visualizer = new PolylineVisualizer(scene, objects); @@ -719,7 +769,7 @@ defineSuite([ } var objects = new EntityCollection(); - var visualizer = new PolylineVisualizer(scene, objects, scene.groundPrimitives); + var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); @@ -759,4 +809,110 @@ defineSuite([ visualizer.destroy(); }); }); + + it('batches ground poylines by material if ground polylines are supported', function() { + if (!Entity.supportsPolylinesOnTerrain(scene)) { + return; + } + + var entities = new EntityCollection(); + var visualizer = new PolylineVisualizer(scene, entities); + + var blueColor = Color.BLUE.withAlpha(0.5); + var redColor = Color.RED.withAlpha(0.5); + var positions = [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]; + entities.add({ + polyline : { + positions : positions, + material : blueColor, + classificationType : ClassificationType.TERRAIN, + clampToGround : true + } + }); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }).then(function() { + expect(scene.groundPrimitives.length).toEqual(1); + + entities.add({ + polyline : { + positions : positions, + material : blueColor, + classificationType : ClassificationType.TERRAIN, + clampToGround : true + } + }); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }); + }).then(function() { + expect(scene.groundPrimitives.length).toEqual(1); + + entities.add({ + polyline : { + positions : positions, + material : redColor, + classificationType : ClassificationType.TERRAIN, + clampToGround : true + } + }); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }); + }).then(function() { + expect(scene.groundPrimitives.length).toEqual(1); + + entities.add({ + polyline : { + positions : positions, + material : new PolylineArrowMaterialProperty(), + classificationType : ClassificationType.TERRAIN, + clampToGround : true + } + }); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }); + }).then(function() { + expect(scene.groundPrimitives.length).toEqual(2); + + entities.add({ + polyline : { + positions : positions, + material : new PolylineArrowMaterialProperty(), + classificationType : ClassificationType.CESIUM_3D_TILE, + clampToGround : true + } + }); + + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }); + }).then(function() { + expect(scene.groundPrimitives.length).toEqual(3); + + entities.removeAll(); + visualizer.destroy(); + }); + }); + }, 'WebGL'); diff --git a/Specs/DataSources/StaticGroundPolylinePerMaterialBatchSpec.js b/Specs/DataSources/StaticGroundPolylinePerMaterialBatchSpec.js index 6fbd74d96407..14bff2aae491 100644 --- a/Specs/DataSources/StaticGroundPolylinePerMaterialBatchSpec.js +++ b/Specs/DataSources/StaticGroundPolylinePerMaterialBatchSpec.js @@ -18,6 +18,7 @@ defineSuite([ 'DataSources/PolylineGeometryUpdater', 'DataSources/PolylineGraphics', 'DataSources/TimeIntervalCollectionProperty', + 'Scene/ClassificationType', 'Scene/GroundPolylinePrimitive', 'Specs/createScene', 'Specs/pollToPromise' @@ -41,6 +42,7 @@ defineSuite([ PolylineGeometryUpdater, PolylineGraphics, TimeIntervalCollectionProperty, + ClassificationType, GroundPolylinePrimitive, createScene, pollToPromise) { @@ -90,7 +92,7 @@ defineSuite([ return; } - batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, false); + batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, ClassificationType.BOTH, false); var polyline1 = createGroundPolyline(); polyline1.material = new PolylineOutlineMaterialProperty(); @@ -151,7 +153,7 @@ defineSuite([ polyline: polyline }); - batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, false); + batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, ClassificationType.BOTH, false); var updater = new PolylineGeometryUpdater(entity, scene); batch.add(validTime, updater); @@ -197,7 +199,7 @@ defineSuite([ polyline: polyline }); - batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, false); + batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, ClassificationType.BOTH, false); var updater = new PolylineGeometryUpdater(entity, scene); batch.add(validTime, updater); @@ -230,7 +232,7 @@ defineSuite([ return; } - batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, false); + batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, ClassificationType.BOTH, false); function buildEntity() { var polyline = createGroundPolyline(); @@ -299,7 +301,7 @@ defineSuite([ return; } - batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, false); + batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, ClassificationType.BOTH, false); var polyline1 = createGroundPolyline(); polyline1.material = Color.RED; var entity = new Entity({ @@ -335,7 +337,7 @@ defineSuite([ return; } - batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, false); + batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, ClassificationType.BOTH, false); var polyline1 = createGroundPolyline(); polyline1.material = new PolylineOutlineMaterialProperty(); @@ -376,7 +378,7 @@ defineSuite([ return; } - batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, false); + batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, ClassificationType.BOTH, false); var polyline1 = createGroundPolyline(); polyline1.material = new PolylineOutlineMaterialProperty(); @@ -417,7 +419,7 @@ defineSuite([ } var resultSphere = new BoundingSphere(); - batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, false); + batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, ClassificationType.BOTH, false); var polyline1 = createGroundPolyline(); polyline1.material = new PolylineOutlineMaterialProperty(); @@ -457,7 +459,7 @@ defineSuite([ // Don't fail if GroundPolylinePrimitive is not supported return; } - batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, false); + batch = new StaticGroundPolylinePerMaterialBatch(scene.groundPrimitives, ClassificationType.BOTH, false); function buildEntity() { var polyline = createGroundPolyline(); From 35223886842533c8ece36c53a4f5d6c8f1921cd2 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Sat, 22 Dec 2018 15:04:44 -0500 Subject: [PATCH 28/39] Add ground polyline to clamp to 3D Tiles demo --- Apps/SampleData/ClampToGround.czml | 28 ++++++++++++++++++ Apps/Sandcastle/gallery/Clamp to 3D Tiles.jpg | Bin 12402 -> 13200 bytes 2 files changed, 28 insertions(+) diff --git a/Apps/SampleData/ClampToGround.czml b/Apps/SampleData/ClampToGround.czml index 04139df57883..9d5abaccd264 100644 --- a/Apps/SampleData/ClampToGround.czml +++ b/Apps/SampleData/ClampToGround.czml @@ -37,5 +37,33 @@ 0.7686388857813198 ] } + }, + { + "id": "Polyline", + "polyline": { + "positions": { + "cartesian": [ + 1216348.1632364073, + -4736348.958775471, + 4081284.5528982095, + 1216369.1229444197, + -4736377.467107148, + 4081240.888485707 + ] + }, + "material": { + "polylineOutline": { + "color": { + "rgba": [255, 255, 0, 255] + }, + "outlineColor": { + "rgba": [0, 0, 0, 255] + }, + "outlineWidth": 2 + } + }, + "width": 10, + "clampToGround": true + } } ] diff --git a/Apps/Sandcastle/gallery/Clamp to 3D Tiles.jpg b/Apps/Sandcastle/gallery/Clamp to 3D Tiles.jpg index 711e53fc19dbb2fef7eaee9e1ddb85461407d5e2..8164f073a8e6ec1309fb11b1c4069d23ae966f58 100644 GIT binary patch delta 13051 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

D=G-{{svyEf@d* From 2d7f4e0405c319eacc47320a001230a853f60f75 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Sat, 22 Dec 2018 15:30:29 -0500 Subject: [PATCH 29/39] Doc fixes --- Source/DataSources/CorridorGraphics.js | 2 +- Source/DataSources/EllipseGraphics.js | 4 ++-- Source/DataSources/Entity.js | 2 +- Source/DataSources/PolygonGraphics.js | 2 +- Source/DataSources/PolylineGraphics.js | 2 +- Source/DataSources/RectangleGraphics.js | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/DataSources/CorridorGraphics.js b/Source/DataSources/CorridorGraphics.js index 5de15e0b003c..aef29581bf11 100644 --- a/Source/DataSources/CorridorGraphics.js +++ b/Source/DataSources/CorridorGraphics.js @@ -41,7 +41,7 @@ define([ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the distance between each latitude and longitude. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the corridor casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this corridor will be displayed. - * @param {Property} [options.classificationType=ClassificationType.BOTH] A Property specifying whether this corridor will classify terrain, 3D Tiles, or both when on the ground. + * @param {Property} [options.classificationType=ClassificationType.BOTH] An enum Property specifying whether this corridor will classify terrain, 3D Tiles, or both when on the ground. * @param {ConstantProperty} [options.zIndex] A Property specifying the zIndex of the corridor, used for ordering. Only has an effect if height and extrudedHeight are undefined, and if the corridor is static. * * @see Entity diff --git a/Source/DataSources/EllipseGraphics.js b/Source/DataSources/EllipseGraphics.js index d909defbabb6..acdf7b9e1d29 100644 --- a/Source/DataSources/EllipseGraphics.js +++ b/Source/DataSources/EllipseGraphics.js @@ -44,8 +44,8 @@ define([ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between points on the ellipse. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the ellipse casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this ellipse will be displayed. - * @param {Property} [options.classificationType=ClassificationType.BOTH] A Property specifying whether this ellipse will classify terrain, 3D Tiles, or both when on the ground. - @param {ConstantProperty} [options.zIndex=0] A property specifying the zIndex of the Ellipse. Used for ordering ground geometry. Only has an effect if the ellipse is constant and neither height or exturdedHeight are specified. + * @param {Property} [options.classificationType=ClassificationType.BOTH] An enum Property specifying whether this ellipse will classify terrain, 3D Tiles, or both when on the ground. + * @param {ConstantProperty} [options.zIndex=0] A property specifying the zIndex of the Ellipse. Used for ordering ground geometry. Only has an effect if the ellipse is constant and neither height or exturdedHeight are specified. * * @demo {@link https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Circles and Ellipses.html|Cesium Sandcastle Circles and Ellipses Demo} */ diff --git a/Source/DataSources/Entity.js b/Source/DataSources/Entity.js index 12479c976706..dae9820c5d4d 100644 --- a/Source/DataSources/Entity.js +++ b/Source/DataSources/Entity.js @@ -681,7 +681,7 @@ define([ * the provided heights and using the `followSurface` parameter instead of clamped to the ground. * * @param {Scene} scene The current scene. - * @returns {Boolean} Whether or not the current scene supports Polylines on Terrain. + * @returns {Boolean} Whether or not the current scene supports polylines on terrain or 3D TIles. */ Entity.supportsPolylinesOnTerrain = function(scene) { return GroundPolylinePrimitive.isSupported(scene); diff --git a/Source/DataSources/PolygonGraphics.js b/Source/DataSources/PolygonGraphics.js index c7ca77ad1258..fb65382cb61e 100644 --- a/Source/DataSources/PolygonGraphics.js +++ b/Source/DataSources/PolygonGraphics.js @@ -43,7 +43,7 @@ define([ * @param {Boolean} [options.closeBottom=true] When false, leaves off the bottom of an extruded polygon open. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the polygon casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this polygon will be displayed. - * @param {Property} [options.classificationType=ClassificationType.BOTH] A Property specifying whether this ellipse will classify terrain, 3D Tiles, or both when on the ground. + * @param {Property} [options.classificationType=ClassificationType.BOTH] An enum Property specifying whether this polygon will classify terrain, 3D Tiles, or both when on the ground. * @param {ConstantProperty} [options.zIndex=0] A property specifying the zIndex used for ordering ground geometry. Only has an effect if the polygon is constant and neither height or extrudedHeight are specified. * * @see Entity diff --git a/Source/DataSources/PolylineGraphics.js b/Source/DataSources/PolylineGraphics.js index 9a79779ca4e5..8f1e912d3cfc 100644 --- a/Source/DataSources/PolylineGraphics.js +++ b/Source/DataSources/PolylineGraphics.js @@ -35,7 +35,7 @@ define([ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude if followSurface is true. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the polyline casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this polyline will be displayed. - * @param {Property} [options.classificationType=ClassificationType.BOTH] A Property specifying whether this polyline will classify terrain, 3D Tiles, or both when on the ground. + * @param {Property} [options.classificationType=ClassificationType.BOTH] An enum Property specifying whether this polyline will classify terrain, 3D Tiles, or both when on the ground. * @param {Property} [options.zIndex=0] A Property specifying the zIndex used for ordering ground geometry. Only has an effect if `clampToGround` is true and polylines on terrain is supported. * * @see Entity diff --git a/Source/DataSources/RectangleGraphics.js b/Source/DataSources/RectangleGraphics.js index 0a7405c195a9..69b251c1a684 100644 --- a/Source/DataSources/RectangleGraphics.js +++ b/Source/DataSources/RectangleGraphics.js @@ -41,7 +41,7 @@ define([ * @param {Property} [options.granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between points on the rectangle. * @param {Property} [options.shadows=ShadowMode.DISABLED] An enum Property specifying whether the rectangle casts or receives shadows from each light source. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this rectangle will be displayed. - * @param {Property} [options.classificationType=ClassificationType.BOTH] A Property specifying whether this rectangle will classify terrain, 3D Tiles, or both when on the ground. + * @param {Property} [options.classificationType=ClassificationType.BOTH] An enum Property specifying whether this rectangle will classify terrain, 3D Tiles, or both when on the ground. * @param {Property} [options.zIndex=0] A Property specifying the zIndex used for ordering ground geometry. Only has an effect if the rectangle is constant and neither height or extrudedHeight are specified. * * @see Entity From 23a16ce0f1a555fbd94b08a81da624d2187cb753 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Sat, 22 Dec 2018 15:42:48 -0500 Subject: [PATCH 30/39] Fix 2D/CV --- Source/Scene/GroundPolylinePrimitive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Scene/GroundPolylinePrimitive.js b/Source/Scene/GroundPolylinePrimitive.js index 896aec902ed8..6dd35dda8dc2 100644 --- a/Source/Scene/GroundPolylinePrimitive.js +++ b/Source/Scene/GroundPolylinePrimitive.js @@ -533,7 +533,7 @@ define([ derived2DCommand.shaderProgram = groundPolylinePrimitive._sp2D; command.derivedCommands.color2D = derived2DCommand; - var derived2DTilesetCommand = DrawCommand.shallowClone(command, derivedTilesetCommand.derivedCommands.color2D); + var derived2DTilesetCommand = DrawCommand.shallowClone(derivedTilesetCommand, derivedTilesetCommand.derivedCommands.color2D); derived2DTilesetCommand.shaderProgram = groundPolylinePrimitive._sp2D; derivedTilesetCommand.derivedCommands.color2D = derived2DTilesetCommand; From 8e94c7c486b97fc71258cecc7cedf90d3caeb1b6 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Sat, 22 Dec 2018 16:18:59 -0500 Subject: [PATCH 31/39] Update CHANGES.md --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 5d2532c5c69b..846b4194ec38 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,8 @@ Change Log ##### Additions :tada: * Added support for textured ground entities (entities with unspecified `height`) and `GroundPrimitives` on 3D Tiles. +* Added support for polylines on 3D Tiles. +* Added `classificationType` property to `PolylineGraphics` and `GroundPolylinePrimitive` which specifies whether a polyline clamped to ground should be clamped to terrain, 3D Tiles, or both. ##### Fixes :wrench: * Fixed an issue where classification primitives with the `CESIUM_3D_TILE` classification type would render on terrain. From 65821fe7b4c3d767c373fcb3a5f5dee0ad79065e Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Sat, 22 Dec 2018 16:27:04 -0500 Subject: [PATCH 32/39] Fix CI --- Specs/DataSources/PolylineVisualizerSpec.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Specs/DataSources/PolylineVisualizerSpec.js b/Specs/DataSources/PolylineVisualizerSpec.js index 26dd30e51bcc..a3f91ebeeb99 100644 --- a/Specs/DataSources/PolylineVisualizerSpec.js +++ b/Specs/DataSources/PolylineVisualizerSpec.js @@ -418,6 +418,10 @@ defineSuite([ }); function createAndRemoveGeometryWithClassificationType(classificationType) { + if (!Entity.supportsPolylinesOnTerrain(scene)) { + return; + } + var objects = new EntityCollection(); var visualizer = new PolylineVisualizer(scene, objects); From 845377934c729fb0fde369cb4df15d01a9901994 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 2 Jan 2019 09:39:51 -0500 Subject: [PATCH 33/39] Move depth update command after invert clsasification --- Source/Scene/Scene.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index bb826571254a..241ecdbb326c 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -2302,10 +2302,6 @@ define([ executeCommand(commands[j], scene, context, passState); } - if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { - globeDepth.executeUpdateDepth(context, passState, clearGlobeDepth); - } - // Set stencil us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW); commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW]; @@ -2328,6 +2324,10 @@ define([ clearClassificationStencil.execute(context, passState); } + if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) { + globeDepth.executeUpdateDepth(context, passState, clearGlobeDepth); + } + // Draw style over classification. us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION); commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION]; From 9e7f30a47516e1a7f565f2367850e68b489e549e Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 2 Jan 2019 10:54:08 -0500 Subject: [PATCH 34/39] Move breaking changes section to the top --- CHANGES.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5d2532c5c69b..516df500175b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,10 @@ Change Log ### 1.54 - 2019-02-01 +##### Breaking Changes :mega: +* Billboards with `HeightReference.CLAMP_TO_GROUND` are now clamped to both terrain and 3D Tiles. +* The default `classificationType` for `GroundPrimitive`, `CorridorGraphics`, `EllipseGraphics`, `PolygonGraphics` and `RectangleGraphics` is now `ClassificationType.BOTH`. + ##### Additions :tada: * Added support for textured ground entities (entities with unspecified `height`) and `GroundPrimitives` on 3D Tiles. @@ -11,10 +15,6 @@ Change Log * Fixed an issue where classification primitives with the `CESIUM_3D_TILE` classification type would render on terrain. * Fixed an issue where 3D Tiles would show through the globe. -##### Breaking Changes :mega: -* Billboards with `HeightReference.CLAMP_TO_GROUND` are now clamped to both terrain and 3D Tiles. -* The default `classificationType` for `GroundPrimitive`, `CorridorGraphics`, `EllipseGraphics`, `PolygonGraphics` and `RectangleGraphics` is now `ClassificationType.BOTH`. - ### 1.53 - 2019-01-02 ##### Fixes :wrench: From 13b82856110a35012e43f4947222c97aa6cf9b68 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 2 Jan 2019 16:02:35 -0500 Subject: [PATCH 35/39] Smaller polylines to speed up tests --- Specs/DataSources/PolylineVisualizerSpec.js | 36 ++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Specs/DataSources/PolylineVisualizerSpec.js b/Specs/DataSources/PolylineVisualizerSpec.js index a3f91ebeeb99..04b06751e870 100644 --- a/Specs/DataSources/PolylineVisualizerSpec.js +++ b/Specs/DataSources/PolylineVisualizerSpec.js @@ -81,7 +81,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new ColorMaterialProperty(); var entity = new Entity(); @@ -120,7 +120,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new PolylineArrowMaterialProperty(); var entity = new Entity(); @@ -163,7 +163,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new ColorMaterialProperty(); polyline.clampToGround = new ConstantProperty(true); @@ -203,7 +203,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new ColorMaterialProperty(); polyline.shadows = new ConstantProperty(shadows); @@ -254,7 +254,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new ColorMaterialProperty(); polyline.depthFailMaterial = new ColorMaterialProperty(); @@ -296,7 +296,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new ColorMaterialProperty(); polyline.depthFailMaterial = new PolylineArrowMaterialProperty(); @@ -338,7 +338,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new PolylineArrowMaterialProperty(); polyline.depthFailMaterial = new PolylineArrowMaterialProperty(); @@ -380,7 +380,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new PolylineArrowMaterialProperty(); polyline.depthFailMaterial = new ColorMaterialProperty(); @@ -426,7 +426,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new ColorMaterialProperty(); polyline.classificationType = new ConstantProperty(classificationType); polyline.clampToGround = true; @@ -474,7 +474,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new ColorMaterialProperty(); var entity = new Entity(); @@ -527,7 +527,7 @@ defineSuite([ var polyline = new PolylineGraphics(); polyline.positions = new CallbackProperty(function() { - return [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]; + return [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]; }, false); polyline.material = new ColorMaterialProperty(); @@ -574,7 +574,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, entityCollection); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new PolylineArrowMaterialProperty(); var entity = new Entity(); @@ -632,7 +632,7 @@ defineSuite([ var entity = new Entity({ id : 'test', polyline : { - positions: [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)], + positions: [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)], material: Color.ORANGE } }); @@ -650,7 +650,7 @@ defineSuite([ id : 'test', position : Cartesian3.fromDegrees(0, 0, 0), polyline : { - positions: [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)], + positions: [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)], material : Color.BLUE } }); @@ -690,7 +690,7 @@ defineSuite([ var entity = entities.add({ polyline : { - positions: [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)], + positions: [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)], material : new ColorMaterialProperty(createDynamicProperty(Color.BLUE)) } }); @@ -732,7 +732,7 @@ defineSuite([ var entity = entities.add({ position : new Cartesian3(1234, 5678, 9101112), polyline : { - positions: [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)], + positions: [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)], material : new PolylineArrowMaterialProperty(createDynamicProperty(Color.BLUE)) } }); @@ -776,7 +776,7 @@ defineSuite([ var visualizer = new PolylineVisualizer(scene, objects); var polyline = new PolylineGraphics(); - polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]); + polyline.positions = new ConstantProperty([Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]); polyline.material = new ColorMaterialProperty(); polyline.clampToGround = new ConstantProperty(true); @@ -824,7 +824,7 @@ defineSuite([ var blueColor = Color.BLUE.withAlpha(0.5); var redColor = Color.RED.withAlpha(0.5); - var positions = [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 1.0)]; + var positions = [Cartesian3.fromDegrees(0.0, 0.0), Cartesian3.fromDegrees(0.0, 0.000001)]; entities.add({ polyline : { positions : positions, From 56b63d191ab9099d9f5996856a3ca1e60722339f Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 2 Jan 2019 16:34:33 -0500 Subject: [PATCH 36/39] Wrap pollToPromise blocks --- Specs/DataSources/GeometryVisualizerSpec.js | 264 ++++---------------- Specs/DataSources/PolylineVisualizerSpec.js | 257 ++++--------------- 2 files changed, 105 insertions(+), 416 deletions(-) diff --git a/Specs/DataSources/GeometryVisualizerSpec.js b/Specs/DataSources/GeometryVisualizerSpec.js index 489d7694c243..f7f0ba49c965 100644 --- a/Specs/DataSources/GeometryVisualizerSpec.js +++ b/Specs/DataSources/GeometryVisualizerSpec.js @@ -82,6 +82,24 @@ defineSuite([ }); + function visualizerUpdated(visualizer) { + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }); + } + + function visualizerEmpty(visualizer) { + return pollToPromise(function() { + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + return scene.primitives.length === 0 && scene.groundPrimitives.length === 0; + }); + } + it('Can create and destroy', function() { var objects = new EntityCollection(); var visualizer = new GeometryVisualizer(scene, objects, scene.primitives, scene.groundPrimitives); @@ -107,12 +125,7 @@ defineSuite([ entity.ellipse = ellipse; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -123,12 +136,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -149,12 +157,7 @@ defineSuite([ entity.ellipse = ellipse; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -165,12 +168,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -191,12 +189,7 @@ defineSuite([ entity.ellipse = ellipse; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -207,12 +200,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -233,12 +221,7 @@ defineSuite([ entity.ellipse = ellipse; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -249,12 +232,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -276,12 +254,7 @@ defineSuite([ entity.ellipse = ellipse; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -291,12 +264,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -318,23 +286,13 @@ defineSuite([ entity.ellipse = ellipse; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); expect(primitive.shadows).toBe(shadows); objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -371,23 +329,13 @@ defineSuite([ entity.ellipse = ellipse; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.groundPrimitives.get(0); expect(primitive.classificationType).toBe(type); objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -420,12 +368,7 @@ defineSuite([ entity.ellipse = ellipse; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -435,12 +378,7 @@ defineSuite([ ellipse.material = new GridMaterialProperty(); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { primitive = scene.primitives.get(0); attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -476,12 +414,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -490,12 +423,7 @@ defineSuite([ color = Color.RED.withAlpha(0.5); entity.ellipse.outlineColor.setValue(color); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); @@ -662,12 +590,7 @@ defineSuite([ }); objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { objects.remove(entity); var entity2 = new Entity({ @@ -682,13 +605,7 @@ defineSuite([ }); objects.add(entity2); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { - + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity2); expect(attributes).toBeDefined(); @@ -698,12 +615,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function() { + return visualizerEmpty(visualizer).then(function() { visualizer.destroy(); }); }); @@ -724,12 +636,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -737,12 +644,7 @@ defineSuite([ entity.show = false; - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); @@ -769,12 +671,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -782,12 +679,7 @@ defineSuite([ entity.show = false; - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); @@ -815,12 +707,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -828,12 +715,7 @@ defineSuite([ entity.show = false; - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); @@ -862,12 +744,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { expect(scene.groundPrimitives.length).toEqual(1); entities.add({ @@ -879,12 +756,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.groundPrimitives.length).toEqual(1); @@ -897,12 +769,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.groundPrimitives.length).toEqual(2); @@ -930,12 +797,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { expect(scene.groundPrimitives.length).toEqual(1); entities.add({ @@ -948,12 +810,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.groundPrimitives.length).toEqual(1); @@ -967,12 +824,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.groundPrimitives.length).toEqual(1); @@ -986,12 +838,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.groundPrimitives.length).toEqual(2); @@ -1005,12 +852,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.groundPrimitives.length).toEqual(3); diff --git a/Specs/DataSources/PolylineVisualizerSpec.js b/Specs/DataSources/PolylineVisualizerSpec.js index 04b06751e870..e288753d9002 100644 --- a/Specs/DataSources/PolylineVisualizerSpec.js +++ b/Specs/DataSources/PolylineVisualizerSpec.js @@ -66,6 +66,24 @@ defineSuite([ ApproximateTerrainHeights._terrainHeights = undefined; }); + function visualizerUpdated(visualizer) { + return pollToPromise(function() { + scene.initializeFrame(); + var isUpdated = visualizer.update(time); + scene.render(time); + return isUpdated; + }); + } + + function visualizerEmpty(visualizer) { + return pollToPromise(function() { + scene.initializeFrame(); + expect(visualizer.update(time)).toBe(true); + scene.render(time); + return scene.primitives.length === 0 && scene.groundPrimitives.length === 0; + }); + } + it('Can create and destroy', function() { var objects = new EntityCollection(); var visualizer = new PolylineVisualizer(scene, objects); @@ -88,12 +106,7 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -104,12 +117,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -127,12 +135,7 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -143,12 +146,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -171,12 +169,7 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.groundPrimitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -187,12 +180,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.groundPrimitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -211,23 +199,13 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); expect(primitive.shadows).toBe(shadows); objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -263,12 +241,7 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -280,12 +253,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -305,12 +273,7 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -322,12 +285,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -347,12 +305,7 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -364,12 +317,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -389,12 +337,7 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -406,12 +349,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -435,23 +373,13 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.groundPrimitives.get(0); expect(primitive.classificationType).toBe(classificationType); objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function(){ + return visualizerEmpty(visualizer).then(function(){ visualizer.destroy(); }); }); @@ -481,12 +409,7 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -496,12 +419,7 @@ defineSuite([ polyline.material = new PolylineArrowMaterialProperty(); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { primitive = scene.primitives.get(0); attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -638,12 +556,7 @@ defineSuite([ }); objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { objects.remove(entity); var entity2 = new Entity({ @@ -656,13 +569,7 @@ defineSuite([ }); objects.add(entity2); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { - + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity2); expect(attributes).toBeDefined(); @@ -672,12 +579,7 @@ defineSuite([ objects.remove(entity); - return pollToPromise(function() { - scene.initializeFrame(); - expect(visualizer.update(time)).toBe(true); - scene.render(time); - return scene.primitives.length === 0; - }).then(function() { + return visualizerEmpty(visualizer).then(function() { visualizer.destroy(); }); }); @@ -695,12 +597,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -708,12 +605,7 @@ defineSuite([ entity.show = false; - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); @@ -737,12 +629,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -750,12 +637,7 @@ defineSuite([ entity.show = false; - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { var primitive = scene.primitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); @@ -784,12 +666,7 @@ defineSuite([ entity.polyline = polyline; objects.add(entity); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { var primitive = scene.groundPrimitives.get(0); var attributes = primitive.getGeometryInstanceAttributes(entity); expect(attributes).toBeDefined(); @@ -800,12 +677,7 @@ defineSuite([ entity.polyline.show = false; - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.primitives.length).toEqual(0); @@ -834,12 +706,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }).then(function() { + return visualizerUpdated(visualizer).then(function() { expect(scene.groundPrimitives.length).toEqual(1); entities.add({ @@ -851,12 +718,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.groundPrimitives.length).toEqual(1); @@ -869,12 +731,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.groundPrimitives.length).toEqual(1); @@ -887,12 +744,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.groundPrimitives.length).toEqual(2); @@ -905,12 +757,7 @@ defineSuite([ } }); - return pollToPromise(function() { - scene.initializeFrame(); - var isUpdated = visualizer.update(time); - scene.render(time); - return isUpdated; - }); + return visualizerUpdated(visualizer); }).then(function() { expect(scene.groundPrimitives.length).toEqual(3); From 2616eeed0fd8a3364818e27bee30c18ac0e02369 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 2 Jan 2019 17:32:15 -0500 Subject: [PATCH 37/39] Remove unneeded shader checks --- Source/Scene/GroundPolylinePrimitive.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Scene/GroundPolylinePrimitive.js b/Source/Scene/GroundPolylinePrimitive.js index 6dd35dda8dc2..b8ebf53ea7a9 100644 --- a/Source/Scene/GroundPolylinePrimitive.js +++ b/Source/Scene/GroundPolylinePrimitive.js @@ -548,9 +548,9 @@ define([ function updateAndQueueCommand(groundPolylinePrimitive, command, frameState, modelMatrix, cull, boundingVolume, debugShowBoundingVolume) { // Use derived appearance command for morph and 2D - if (frameState.mode === SceneMode.MORPHING && command.shaderProgram !== groundPolylinePrimitive._spMorph) { + if (frameState.mode === SceneMode.MORPHING) { command = command.derivedCommands.colorMorph; - } else if (frameState.mode !== SceneMode.SCENE3D && command.shaderProgram !== groundPolylinePrimitive._sp2D) { + } else if (frameState.mode !== SceneMode.SCENE3D) { command = command.derivedCommands.color2D; } command.modelMatrix = modelMatrix; From 3729e7054994eb8861cb643212110cd324d90d77 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 2 Jan 2019 17:47:53 -0500 Subject: [PATCH 38/39] Update Sandcastle demo --- .../gallery/Classification Types.html | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/Apps/Sandcastle/gallery/Classification Types.html b/Apps/Sandcastle/gallery/Classification Types.html index c1d6c8d3d4b4..59a8182ed9da 100644 --- a/Apps/Sandcastle/gallery/Classification Types.html +++ b/Apps/Sandcastle/gallery/Classification Types.html @@ -40,7 +40,7 @@ viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); }); -var entity = viewer.entities.add({ +var polygon = viewer.entities.add({ polygon : { hierarchy : new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromRadiansArray([-1.3194369277314022, 0.6988062530900625, -1.3193955980204217, 0.6988091578771254, -1.3193931220959367, 0.698743632490865, -1.3194358224045408, 0.6987471965556998])), material : Cesium.Color.RED.withAlpha(0.5), @@ -48,32 +48,60 @@ } }); +var polyline = viewer.entities.add({ + polyline : { + positions : Cesium.Cartesian3.fromDegreesArray([ + -75.60217330403601, 40.04102882709425, + -75.59968252414251, 40.04093615560871, + -75.59802015382800, 40.04079437042357, + -75.59674934074435, 40.040816173283304, + -75.59630042791713, 40.03986900370842, + -75.59563636849978, 40.03930996506271, + -75.59492397899098, 40.03873932846581, + -75.59457991226778, 40.038392701955786, + -75.59424838652453, 40.03775403572295, + -75.59387104290336, 40.03677022167725, + -75.59355000490342, 40.03588760913535 + ]), + width : 8, + material : new Cesium.PolylineOutlineMaterialProperty({ + color : Cesium.Color.YELLOW, + outlineWidth : 2, + outlineColor : Cesium.Color.BLACK + }), + clampToGround : true + } +}); + var classificationOptions = [{ text : 'Classify Both', onselect : function() { - entity.polygon.classificationType = Cesium.ClassificationType.BOTH; + polygon.polygon.classificationType = Cesium.ClassificationType.BOTH; + polyline.polyline.classificationType = Cesium.ClassificationType.BOTH; } }, { text : 'Classify Terrain', onselect : function() { - entity.polygon.classificationType = Cesium.ClassificationType.TERRAIN; + polygon.polygon.classificationType = Cesium.ClassificationType.TERRAIN; + polyline.polyline.classificationType = Cesium.ClassificationType.TERRAIN; } }, { text : 'Classify 3D Tiles', onselect : function() { - entity.polygon.classificationType = Cesium.ClassificationType.CESIUM_3D_TILE; + polygon.polygon.classificationType = Cesium.ClassificationType.CESIUM_3D_TILE; + polyline.polyline.classificationType = Cesium.ClassificationType.CESIUM_3D_TILE; } }]; var materialOptions = [{ text : 'Red Material', onselect : function() { - entity.polygon.material = Cesium.Color.RED.withAlpha(0.5); + polygon.polygon.material = Cesium.Color.RED.withAlpha(0.5); } }, { text : 'Textured Material', onselect : function() { - entity.polygon.material = '../images/Cesium_Logo_Color.jpg'; + polygon.polygon.material = '../images/Cesium_Logo_Color.jpg'; } }]; From 290b531c2b85269a656ed2ecdccf0214ed3d2bc0 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 3 Jan 2019 17:25:40 -0500 Subject: [PATCH 39/39] Fix test --- Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js b/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js index 72dee4cc1839..e20dd620dcf5 100644 --- a/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js +++ b/Specs/DataSources/StaticGroundGeometryPerMaterialBatchSpec.js @@ -205,7 +205,7 @@ defineSuite([ } }); - var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, MaterialAppearance); + var batch = new StaticGroundGeometryPerMaterialBatch(scene.primitives, ClassificationType.BOTH, MaterialAppearance); var updater = new EllipseGeometryUpdater(entity, scene); batch.add(validTime, updater);