1035 lines
42 KiB
JavaScript
1035 lines
42 KiB
JavaScript
|
|
defineSuite([
|
||
|
|
'Scene/PointCloud3DTileContent',
|
||
|
|
'Core/Cartesian3',
|
||
|
|
'Core/Color',
|
||
|
|
'Core/ComponentDatatype',
|
||
|
|
'Core/defined',
|
||
|
|
'Core/HeadingPitchRange',
|
||
|
|
'Core/HeadingPitchRoll',
|
||
|
|
'Core/Math',
|
||
|
|
'Core/Matrix4',
|
||
|
|
'Core/PerspectiveFrustum',
|
||
|
|
'Core/Transforms',
|
||
|
|
'Renderer/Pass',
|
||
|
|
'Scene/Cesium3DTileRefine',
|
||
|
|
'Scene/Cesium3DTileStyle',
|
||
|
|
'Scene/ClippingPlane',
|
||
|
|
'Scene/ClippingPlaneCollection',
|
||
|
|
'Scene/DracoLoader',
|
||
|
|
'Scene/Expression',
|
||
|
|
'Specs/Cesium3DTilesTester',
|
||
|
|
'Specs/createCanvas',
|
||
|
|
'Specs/createScene',
|
||
|
|
'Specs/pollToPromise',
|
||
|
|
'ThirdParty/when'
|
||
|
|
], function(
|
||
|
|
PointCloud3DTileContent,
|
||
|
|
Cartesian3,
|
||
|
|
Color,
|
||
|
|
ComponentDatatype,
|
||
|
|
defined,
|
||
|
|
HeadingPitchRange,
|
||
|
|
HeadingPitchRoll,
|
||
|
|
CesiumMath,
|
||
|
|
Matrix4,
|
||
|
|
PerspectiveFrustum,
|
||
|
|
Transforms,
|
||
|
|
Pass,
|
||
|
|
Cesium3DTileRefine,
|
||
|
|
Cesium3DTileStyle,
|
||
|
|
ClippingPlane,
|
||
|
|
ClippingPlaneCollection,
|
||
|
|
DracoLoader,
|
||
|
|
Expression,
|
||
|
|
Cesium3DTilesTester,
|
||
|
|
createCanvas,
|
||
|
|
createScene,
|
||
|
|
pollToPromise,
|
||
|
|
when) {
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
var scene;
|
||
|
|
var centerLongitude = -1.31968;
|
||
|
|
var centerLatitude = 0.698874;
|
||
|
|
|
||
|
|
var pointCloudRGBUrl = './Data/Cesium3DTiles/PointCloud/PointCloudRGB/tileset.json';
|
||
|
|
var pointCloudRGBAUrl = './Data/Cesium3DTiles/PointCloud/PointCloudRGBA/tileset.json';
|
||
|
|
var pointCloudRGB565Url = './Data/Cesium3DTiles/PointCloud/PointCloudRGB565/tileset.json';
|
||
|
|
var pointCloudNoColorUrl = './Data/Cesium3DTiles/PointCloud/PointCloudNoColor/tileset.json';
|
||
|
|
var pointCloudConstantColorUrl = './Data/Cesium3DTiles/PointCloud/PointCloudConstantColor/tileset.json';
|
||
|
|
var pointCloudNormalsUrl = './Data/Cesium3DTiles/PointCloud/PointCloudNormals/tileset.json';
|
||
|
|
var pointCloudNormalsOctEncodedUrl = './Data/Cesium3DTiles/PointCloud/PointCloudNormalsOctEncoded/tileset.json';
|
||
|
|
var pointCloudQuantizedUrl = './Data/Cesium3DTiles/PointCloud/PointCloudQuantized/tileset.json';
|
||
|
|
var pointCloudQuantizedOctEncodedUrl = './Data/Cesium3DTiles/PointCloud/PointCloudQuantizedOctEncoded/tileset.json';
|
||
|
|
var pointCloudDracoUrl = './Data/Cesium3DTiles/PointCloud/PointCloudDraco/tileset.json';
|
||
|
|
var pointCloudDracoPartialUrl = './Data/Cesium3DTiles/PointCloud/PointCloudDracoPartial/tileset.json';
|
||
|
|
var pointCloudDracoBatchedUrl = './Data/Cesium3DTiles/PointCloud/PointCloudDracoBatched/tileset.json';
|
||
|
|
var pointCloudWGS84Url = './Data/Cesium3DTiles/PointCloud/PointCloudWGS84/tileset.json';
|
||
|
|
var pointCloudBatchedUrl = './Data/Cesium3DTiles/PointCloud/PointCloudBatched/tileset.json';
|
||
|
|
var pointCloudWithPerPointPropertiesUrl = './Data/Cesium3DTiles/PointCloud/PointCloudWithPerPointProperties/tileset.json';
|
||
|
|
var pointCloudWithTransformUrl = './Data/Cesium3DTiles/PointCloud/PointCloudWithTransform/tileset.json';
|
||
|
|
var pointCloudTilesetUrl = './Data/Cesium3DTiles/Tilesets/TilesetPoints/tileset.json';
|
||
|
|
|
||
|
|
function setCamera(longitude, latitude) {
|
||
|
|
// Point the camera to the center of the tile
|
||
|
|
var center = Cartesian3.fromRadians(longitude, latitude, 5.0);
|
||
|
|
scene.camera.lookAt(center, new HeadingPitchRange(0.0, -1.57, 5.0));
|
||
|
|
}
|
||
|
|
|
||
|
|
beforeAll(function() {
|
||
|
|
scene = createScene();
|
||
|
|
scene.frameState.passes.render = true;
|
||
|
|
});
|
||
|
|
|
||
|
|
afterAll(function() {
|
||
|
|
scene.destroyForSpecs();
|
||
|
|
});
|
||
|
|
|
||
|
|
beforeEach(function() {
|
||
|
|
scene.morphTo3D(0.0);
|
||
|
|
|
||
|
|
var camera = scene.camera;
|
||
|
|
camera.frustum = new PerspectiveFrustum();
|
||
|
|
camera.frustum.aspectRatio = scene.drawingBufferWidth / scene.drawingBufferHeight;
|
||
|
|
camera.frustum.fov = CesiumMath.toRadians(60.0);
|
||
|
|
|
||
|
|
setCamera(centerLongitude, centerLatitude);
|
||
|
|
});
|
||
|
|
|
||
|
|
afterEach(function() {
|
||
|
|
scene.primitives.removeAll();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws with invalid version', function() {
|
||
|
|
var arrayBuffer = Cesium3DTilesTester.generatePointCloudTileBuffer({
|
||
|
|
version: 2
|
||
|
|
});
|
||
|
|
Cesium3DTilesTester.loadTileExpectError(scene, arrayBuffer, 'pnts');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws if featureTableJsonByteLength is 0', function() {
|
||
|
|
var arrayBuffer = Cesium3DTilesTester.generatePointCloudTileBuffer({
|
||
|
|
featureTableJsonByteLength : 0
|
||
|
|
});
|
||
|
|
Cesium3DTilesTester.loadTileExpectError(scene, arrayBuffer, 'pnts');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws if the feature table does not contain POINTS_LENGTH', function() {
|
||
|
|
var arrayBuffer = Cesium3DTilesTester.generatePointCloudTileBuffer({
|
||
|
|
featureTableJson : {
|
||
|
|
POSITION : {
|
||
|
|
byteOffset : 0
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
Cesium3DTilesTester.loadTileExpectError(scene, arrayBuffer, 'pnts');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws if the feature table does not contain POSITION or POSITION_QUANTIZED', function() {
|
||
|
|
var arrayBuffer = Cesium3DTilesTester.generatePointCloudTileBuffer({
|
||
|
|
featureTableJson : {
|
||
|
|
POINTS_LENGTH : 1
|
||
|
|
}
|
||
|
|
});
|
||
|
|
Cesium3DTilesTester.loadTileExpectError(scene, arrayBuffer, 'pnts');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws if the positions are quantized and the feature table does not contain QUANTIZED_VOLUME_SCALE', function() {
|
||
|
|
var arrayBuffer = Cesium3DTilesTester.generatePointCloudTileBuffer({
|
||
|
|
featureTableJson : {
|
||
|
|
POINTS_LENGTH : 1,
|
||
|
|
POSITION_QUANTIZED : {
|
||
|
|
byteOffset : 0
|
||
|
|
},
|
||
|
|
QUANTIZED_VOLUME_OFFSET : [0.0, 0.0, 0.0]
|
||
|
|
}
|
||
|
|
});
|
||
|
|
Cesium3DTilesTester.loadTileExpectError(scene, arrayBuffer, 'pnts');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws if the positions are quantized and the feature table does not contain QUANTIZED_VOLUME_OFFSET', function() {
|
||
|
|
var arrayBuffer = Cesium3DTilesTester.generatePointCloudTileBuffer({
|
||
|
|
featureTableJson : {
|
||
|
|
POINTS_LENGTH : 1,
|
||
|
|
POSITION_QUANTIZED : {
|
||
|
|
byteOffset : 0
|
||
|
|
},
|
||
|
|
QUANTIZED_VOLUME_SCALE : [1.0, 1.0, 1.0]
|
||
|
|
}
|
||
|
|
});
|
||
|
|
Cesium3DTilesTester.loadTileExpectError(scene, arrayBuffer, 'pnts');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws if the BATCH_ID semantic is defined but BATCHES_LENGTH is not', function() {
|
||
|
|
var arrayBuffer = Cesium3DTilesTester.generatePointCloudTileBuffer({
|
||
|
|
featureTableJson : {
|
||
|
|
POINTS_LENGTH : 2,
|
||
|
|
POSITION : [0.0, 0.0, 0.0, 1.0, 1.0, 1.0],
|
||
|
|
BATCH_ID : [0, 1]
|
||
|
|
}
|
||
|
|
});
|
||
|
|
Cesium3DTilesTester.loadTileExpectError(scene, arrayBuffer, 'pnts');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('BATCH_ID semantic uses componentType of UNSIGNED_SHORT by default', function() {
|
||
|
|
var arrayBuffer = Cesium3DTilesTester.generatePointCloudTileBuffer({
|
||
|
|
featureTableJson : {
|
||
|
|
POINTS_LENGTH : 2,
|
||
|
|
POSITION : [0.0, 0.0, 0.0, 1.0, 1.0, 1.0],
|
||
|
|
BATCH_ID : [0, 1],
|
||
|
|
BATCH_LENGTH : 2
|
||
|
|
}
|
||
|
|
});
|
||
|
|
var content = Cesium3DTilesTester.loadTile(scene, arrayBuffer, 'pnts');
|
||
|
|
expect(content._pointCloud._drawCommand._vertexArray._attributes[1].componentDatatype).toEqual(ComponentDatatype.UNSIGNED_SHORT);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('gets tileset properties', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
var content = root.content;
|
||
|
|
expect(content.tileset).toBe(tileset);
|
||
|
|
expect(content.tile).toBe(root);
|
||
|
|
expect(content.url.indexOf(root._header.content.uri) > -1).toBe(true);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('resolves readyPromise', function() {
|
||
|
|
return Cesium3DTilesTester.resolvesReadyPromise(scene, pointCloudRGBUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with rgb colors', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with rgba colors', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBAUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with rgb565 colors', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGB565Url).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with no colors', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudNoColorUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with constant colors', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudConstantColorUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with normals', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudNormalsUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with oct encoded normals', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudNormalsOctEncodedUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with quantized positions', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudQuantizedUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with quantized positions and oct-encoded normals', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudQuantizedOctEncodedUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with draco encoded positions, normals, colors, and batch table properties', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudDracoUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
// Test that Draco-encoded batch table properties are functioning correctly
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'vec4(Number(${secondaryColor}[0] < 1.0), 0.0, 0.0, 1.0)'
|
||
|
|
});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
// Produces a red color
|
||
|
|
expect(rgba[0]).toBeGreaterThan(rgba[1]);
|
||
|
|
expect(rgba[0]).toBeGreaterThan(rgba[2]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with draco encoded positions and uncompressed normals and colors', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudDracoPartialUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with draco encoded positions, colors, and batch ids', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudDracoBatchedUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('error decoding a draco point cloud causes loading to fail', function() {
|
||
|
|
return pollToPromise(function() {
|
||
|
|
return DracoLoader._taskProcessorReady;
|
||
|
|
}).then(function() {
|
||
|
|
var decoder = DracoLoader._getDecoderTaskProcessor();
|
||
|
|
spyOn(decoder, 'scheduleTask').and.returnValue(when.reject({message : 'my error'}));
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudDracoUrl).then(function(tileset) {
|
||
|
|
var root = tileset.root;
|
||
|
|
return root.contentReadyPromise.then(function() {
|
||
|
|
fail('should not resolve');
|
||
|
|
}).otherwise(function(error) {
|
||
|
|
expect(error.message).toBe('my error');
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud that are not defined relative to center', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudWGS84Url).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with batch table', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudBatchedUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with per-point properties', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudWithPerPointPropertiesUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders point cloud with tile transform', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudWithTransformUrl).then(function(tileset) {
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
|
||
|
|
var newLongitude = -1.31962;
|
||
|
|
var newLatitude = 0.698874;
|
||
|
|
var newCenter = Cartesian3.fromRadians(newLongitude, newLatitude, 5.0);
|
||
|
|
var newHPR = new HeadingPitchRoll();
|
||
|
|
var newTransform = Transforms.headingPitchRollToFixedFrame(newCenter, newHPR);
|
||
|
|
|
||
|
|
// Update tile transform
|
||
|
|
tileset.root.transform = newTransform;
|
||
|
|
|
||
|
|
// Move the camera to the new location
|
||
|
|
setCamera(newLongitude, newLatitude);
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders with debug color', function() {
|
||
|
|
CesiumMath.setRandomNumberSeed(0);
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
var color;
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
color = rgba;
|
||
|
|
});
|
||
|
|
tileset.debugColorizeTiles = true;
|
||
|
|
expect(scene).notToRender(color);
|
||
|
|
tileset.debugColorizeTiles = false;
|
||
|
|
expect(scene).toRender(color);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders in CV', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
scene.morphToColumbusView(0.0);
|
||
|
|
setCamera(centerLongitude, centerLatitude);
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders in 2D', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
scene.morphTo2D(0.0);
|
||
|
|
setCamera(centerLongitude, centerLatitude);
|
||
|
|
tileset.maximumScreenSpaceError = 3;
|
||
|
|
Cesium3DTilesTester.expectRender(scene, tileset);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('picks', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
var content = tileset.root.content;
|
||
|
|
tileset.show = false;
|
||
|
|
expect(scene).toPickPrimitive(undefined);
|
||
|
|
tileset.show = true;
|
||
|
|
expect(scene).toPickAndCall(function(result) {
|
||
|
|
expect(result).toBeDefined();
|
||
|
|
expect(result.primitive).toBe(tileset);
|
||
|
|
expect(result.content).toBe(content);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('picks based on batchId', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudBatchedUrl).then(function(tileset) {
|
||
|
|
// Get the original color
|
||
|
|
var color;
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
color = rgba;
|
||
|
|
});
|
||
|
|
|
||
|
|
// Change the color of the picked feature to yellow
|
||
|
|
expect(scene).toPickAndCall(function(first) {
|
||
|
|
expect(first).toBeDefined();
|
||
|
|
|
||
|
|
first.color = Color.clone(Color.YELLOW, first.color);
|
||
|
|
|
||
|
|
// Expect the pixel color to be some shade of yellow
|
||
|
|
expect(scene).notToRender(color);
|
||
|
|
|
||
|
|
// Turn show off. Expect a different feature to get picked.
|
||
|
|
first.show = false;
|
||
|
|
expect(scene).toPickAndCall(function(second) {
|
||
|
|
expect(second).toBeDefined();
|
||
|
|
expect(second).not.toBe(first);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('point cloud without batch table works', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
var content = tileset.root.content;
|
||
|
|
expect(content.featuresLength).toBe(0);
|
||
|
|
expect(content.innerContents).toBeUndefined();
|
||
|
|
expect(content.hasProperty(0, 'name')).toBe(false);
|
||
|
|
expect(content.getFeature(0)).toBeUndefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('batched point cloud works', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudBatchedUrl).then(function(tileset) {
|
||
|
|
var content = tileset.root.content;
|
||
|
|
expect(content.featuresLength).toBe(8);
|
||
|
|
expect(content.innerContents).toBeUndefined();
|
||
|
|
expect(content.hasProperty(0, 'name')).toBe(true);
|
||
|
|
expect(content.getFeature(0)).toBeDefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('point cloud with per-point properties work', function() {
|
||
|
|
// When the batch table contains per-point properties, aka no batching, then a Cesium3DTileBatchTable is not
|
||
|
|
// created. There is no per-point show/color/pickId because the overhead is too high. Instead points are styled
|
||
|
|
// based on their properties, and these are not accessible from the API.
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudWithPerPointPropertiesUrl).then(function(tileset) {
|
||
|
|
var content = tileset.root.content;
|
||
|
|
expect(content.featuresLength).toBe(0);
|
||
|
|
expect(content.innerContents).toBeUndefined();
|
||
|
|
expect(content.hasProperty(0, 'name')).toBe(false);
|
||
|
|
expect(content.getFeature(0)).toBeUndefined();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws when calling getFeature with invalid index', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudBatchedUrl).then(function(tileset) {
|
||
|
|
var content = tileset.root.content;
|
||
|
|
expect(function(){
|
||
|
|
content.getFeature(-1);
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
expect(function(){
|
||
|
|
content.getFeature(1000);
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
expect(function(){
|
||
|
|
content.getFeature();
|
||
|
|
}).toThrowDeveloperError();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('Supports back face culling when there are per-point normals', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudBatchedUrl).then(function(tileset) {
|
||
|
|
var content = tileset.root.content;
|
||
|
|
|
||
|
|
// Get the number of picked sections with back face culling on
|
||
|
|
var pickedCountCulling = 0;
|
||
|
|
var pickedCount = 0;
|
||
|
|
var picked;
|
||
|
|
|
||
|
|
expect(scene).toPickAndCall(function(result) {
|
||
|
|
// Set culling to true
|
||
|
|
content._pointCloud.backFaceCulling = true;
|
||
|
|
|
||
|
|
expect(scene).toPickAndCall(function(result) {
|
||
|
|
picked = result;
|
||
|
|
});
|
||
|
|
|
||
|
|
/* jshint loopfunc: true */
|
||
|
|
while (defined(picked)) {
|
||
|
|
picked.show = false;
|
||
|
|
expect(scene).toPickAndCall(function(result) { //eslint-disable-line no-loop-func
|
||
|
|
picked = result;
|
||
|
|
});
|
||
|
|
++pickedCountCulling;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set the shows back to true
|
||
|
|
var length = content.featuresLength;
|
||
|
|
for (var i = 0; i < length; ++i) {
|
||
|
|
var feature = content.getFeature(i);
|
||
|
|
feature.show = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set culling to false
|
||
|
|
content._pointCloud.backFaceCulling = false;
|
||
|
|
|
||
|
|
expect(scene).toPickAndCall(function(result) {
|
||
|
|
picked = result;
|
||
|
|
});
|
||
|
|
|
||
|
|
/* jshint loopfunc: true */
|
||
|
|
while (defined(picked)) {
|
||
|
|
picked.show = false;
|
||
|
|
expect(scene).toPickAndCall(function(result) { //eslint-disable-line no-loop-func
|
||
|
|
picked = result;
|
||
|
|
});
|
||
|
|
++pickedCount;
|
||
|
|
}
|
||
|
|
|
||
|
|
expect(pickedCount).toBeGreaterThan(pickedCountCulling);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
var noAttenuationPixelCount;
|
||
|
|
function attenuationTest(postLoadCallback) {
|
||
|
|
var scene = createScene({
|
||
|
|
canvas : createCanvas(10, 10)
|
||
|
|
});
|
||
|
|
noAttenuationPixelCount = scene.logarithmicDepthBuffer ? 20 : 16;
|
||
|
|
var center = new Cartesian3.fromRadians(centerLongitude, centerLatitude, 5.0);
|
||
|
|
scene.camera.lookAt(center, new HeadingPitchRange(0.0, -1.57, 5.0));
|
||
|
|
scene.postProcessStages.fxaa.enabled = false;
|
||
|
|
scene.camera.zoomIn(6);
|
||
|
|
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudNoColorUrl).then(function(tileset) {
|
||
|
|
tileset.pointCloudShading.eyeDomeLighting = false;
|
||
|
|
tileset.root.refine = Cesium3DTileRefine.REPLACE;
|
||
|
|
postLoadCallback(scene, tileset);
|
||
|
|
scene.destroyForSpecs();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
it('attenuates points based on geometric error', function() {
|
||
|
|
return attenuationTest(function(scene, tileset) {
|
||
|
|
tileset.pointCloudShading.attenuation = true;
|
||
|
|
tileset.pointCloudShading.geometricErrorScale = 1.0;
|
||
|
|
tileset.pointCloudShading.maximumAttenuation = undefined;
|
||
|
|
tileset.pointCloudShading.baseResolution = undefined;
|
||
|
|
tileset.maximumScreenSpaceError = 16;
|
||
|
|
expect(scene).toRenderPixelCountAndCall(function(pixelCount) {
|
||
|
|
expect(pixelCount).toBeGreaterThan(noAttenuationPixelCount);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('modulates attenuation using the tileset screen space error', function() {
|
||
|
|
return attenuationTest(function(scene, tileset) {
|
||
|
|
tileset.pointCloudShading.attenuation = true;
|
||
|
|
tileset.pointCloudShading.geometricErrorScale = 1.0;
|
||
|
|
tileset.pointCloudShading.maximumAttenuation = undefined;
|
||
|
|
tileset.pointCloudShading.baseResolution = undefined;
|
||
|
|
tileset.maximumScreenSpaceError = 1;
|
||
|
|
expect(scene).toRenderPixelCountAndCall(function(pixelCount) {
|
||
|
|
expect(pixelCount).toEqual(noAttenuationPixelCount);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('modulates attenuation using the maximumAttenuation parameter', function() {
|
||
|
|
return attenuationTest(function(scene, tileset) {
|
||
|
|
tileset.pointCloudShading.attenuation = true;
|
||
|
|
tileset.pointCloudShading.geometricErrorScale = 1.0;
|
||
|
|
tileset.pointCloudShading.maximumAttenuation = 1;
|
||
|
|
tileset.pointCloudShading.baseResolution = undefined;
|
||
|
|
tileset.maximumScreenSpaceError = 16;
|
||
|
|
expect(scene).toRenderPixelCountAndCall(function(pixelCount) {
|
||
|
|
expect(pixelCount).toEqual(noAttenuationPixelCount);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('modulates attenuation using the baseResolution parameter', function() {
|
||
|
|
return attenuationTest(function(scene, tileset) {
|
||
|
|
// pointCloudNoColorUrl is a single tile with GeometricError = 0,
|
||
|
|
// which results in default baseResolution being computed
|
||
|
|
tileset.pointCloudShading.attenuation = true;
|
||
|
|
tileset.pointCloudShading.geometricErrorScale = 1.0;
|
||
|
|
tileset.pointCloudShading.maximumAttenuation = undefined;
|
||
|
|
tileset.pointCloudShading.baseResolution = 0.20;
|
||
|
|
tileset.maximumScreenSpaceError = 16;
|
||
|
|
expect(scene).toRenderPixelCountAndCall(function(pixelCount) {
|
||
|
|
expect(pixelCount).toEqual(noAttenuationPixelCount);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('modulates attenuation using the geometricErrorScale parameter', function() {
|
||
|
|
return attenuationTest(function(scene, tileset) {
|
||
|
|
tileset.pointCloudShading.attenuation = true;
|
||
|
|
tileset.pointCloudShading.geometricErrorScale = 0.2;
|
||
|
|
tileset.pointCloudShading.maximumAttenuation = undefined;
|
||
|
|
tileset.pointCloudShading.baseResolution = 1.0;
|
||
|
|
tileset.maximumScreenSpaceError = 1;
|
||
|
|
expect(scene).toRenderPixelCountAndCall(function(pixelCount) {
|
||
|
|
expect(pixelCount).toEqual(noAttenuationPixelCount);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('attenuates points based on geometric error in 2D', function() {
|
||
|
|
return attenuationTest(function(scene, tileset) {
|
||
|
|
scene.morphTo2D(0);
|
||
|
|
tileset.pointCloudShading.attenuation = true;
|
||
|
|
tileset.pointCloudShading.geometricErrorScale = 1.0;
|
||
|
|
tileset.pointCloudShading.maximumAttenuation = undefined;
|
||
|
|
tileset.pointCloudShading.baseResolution = undefined;
|
||
|
|
tileset.maximumScreenSpaceError = 16;
|
||
|
|
expect(scene).toRenderPixelCountAndCall(function(pixelCount) {
|
||
|
|
expect(pixelCount).toBeGreaterThan(noAttenuationPixelCount);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies shader style', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudWithPerPointPropertiesUrl).then(function(tileset) {
|
||
|
|
var content = tileset.root.content;
|
||
|
|
|
||
|
|
// Solid red color
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'color("red")'
|
||
|
|
});
|
||
|
|
expect(scene).toRender([255, 0, 0, 255]);
|
||
|
|
expect(content._pointCloud._styleTranslucent).toBe(false);
|
||
|
|
|
||
|
|
// Applies translucency
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'rgba(255, 0, 0, 0.005)'
|
||
|
|
});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
// Pixel is a darker red
|
||
|
|
expect(rgba[0]).toBeLessThan(255);
|
||
|
|
expect(rgba[1]).toBe(0);
|
||
|
|
expect(rgba[2]).toBe(0);
|
||
|
|
expect(rgba[3]).toBe(255);
|
||
|
|
expect(content._pointCloud._styleTranslucent).toBe(true);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Style with property
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'color() * ${temperature}'
|
||
|
|
});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
// Pixel color is some shade of gray
|
||
|
|
expect(rgba[0]).toBe(rgba[1]);
|
||
|
|
expect(rgba[0]).toBe(rgba[2]);
|
||
|
|
expect(rgba[0]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[0]).toBeLessThan(255);
|
||
|
|
});
|
||
|
|
|
||
|
|
// When no conditions are met the default color is white
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : {
|
||
|
|
conditions : [
|
||
|
|
['${secondaryColor}[0] > 1.0', 'color("red")'] // This condition will not be met
|
||
|
|
]
|
||
|
|
}
|
||
|
|
});
|
||
|
|
expect(scene).toRender([255, 255, 255, 255]);
|
||
|
|
|
||
|
|
// Apply style with conditions
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : {
|
||
|
|
conditions : [
|
||
|
|
['${temperature} < 0.1', 'color("#000099")'],
|
||
|
|
['${temperature} < 0.2', 'color("#00cc99", 1.0)'],
|
||
|
|
['${temperature} < 0.3', 'color("#66ff33", 0.5)'],
|
||
|
|
['${temperature} < 0.4', 'rgba(255, 255, 0, 0.1)'],
|
||
|
|
['${temperature} < 0.5', 'rgb(255, 128, 0)'],
|
||
|
|
['${temperature} < 0.6', 'color("red")'],
|
||
|
|
['${temperature} < 0.7', 'color("rgb(255, 102, 102)")'],
|
||
|
|
['${temperature} < 0.8', 'hsl(0.875, 1.0, 0.6)'],
|
||
|
|
['${temperature} < 0.9', 'hsla(0.83, 1.0, 0.5, 0.1)'],
|
||
|
|
['true', 'color("#FFFFFF", 1.0)']
|
||
|
|
]
|
||
|
|
}
|
||
|
|
});
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
// Apply show style
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
show : true
|
||
|
|
});
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
// Apply show style that hides all points
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
show : false
|
||
|
|
});
|
||
|
|
expect(scene).toRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
// Apply show style with property
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
show : '${temperature} > 0.1'
|
||
|
|
});
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
show : '${temperature} > 1.0'
|
||
|
|
});
|
||
|
|
expect(scene).toRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
// Apply style with point cloud semantics
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : '${COLOR} / 2.0',
|
||
|
|
show : '${POSITION}[0] > 0.5'
|
||
|
|
});
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
|
||
|
|
// Apply pointSize style
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
pointSize : 5.0
|
||
|
|
});
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('rebuilds shader style when expression changes', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudTilesetUrl).then(function(tileset) {
|
||
|
|
// Solid red color
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'color("red")'
|
||
|
|
});
|
||
|
|
expect(scene).toRender([255, 0, 0, 255]);
|
||
|
|
|
||
|
|
tileset.style.color = new Expression('color("lime")');
|
||
|
|
tileset.makeStyleDirty();
|
||
|
|
expect(scene).toRender([0, 255, 0, 255]);
|
||
|
|
|
||
|
|
tileset.style.color = new Expression('color("blue", 0.5)');
|
||
|
|
tileset.makeStyleDirty();
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba).toEqualEpsilon([0, 0, 255, 255], 5);
|
||
|
|
});
|
||
|
|
|
||
|
|
var i;
|
||
|
|
var commands = scene.frameState.commandList;
|
||
|
|
var commandsLength = commands.length;
|
||
|
|
expect(commandsLength).toBeGreaterThan(1); // Just check that at least some children are rendered
|
||
|
|
for (i = 0; i < commandsLength; ++i) {
|
||
|
|
expect(commands[i].pass).toBe(Pass.TRANSLUCENT);
|
||
|
|
}
|
||
|
|
|
||
|
|
tileset.style.color = new Expression('color("yellow")');
|
||
|
|
tileset.makeStyleDirty();
|
||
|
|
expect(scene).toRender([255, 255, 0, 255]);
|
||
|
|
|
||
|
|
commands = scene.frameState.commandList;
|
||
|
|
commandsLength = commands.length;
|
||
|
|
for (i = 0; i < commandsLength; ++i) {
|
||
|
|
expect(commands[i].pass).not.toBe(Pass.TRANSLUCENT);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies shader style to point cloud with normals', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudQuantizedOctEncodedUrl).then(function(tileset) {
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'color("red")'
|
||
|
|
});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(0);
|
||
|
|
expect(rgba[0]).toBeLessThan(255);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies shader style to point cloud with normals', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudQuantizedOctEncodedUrl).then(function(tileset) {
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'color("red")'
|
||
|
|
});
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
expect(rgba[0]).toBeGreaterThan(0);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('applies shader style to point cloud without colors', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudNoColorUrl).then(function(tileset) {
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'color("red")'
|
||
|
|
});
|
||
|
|
expect(scene).toRender([255, 0, 0, 255]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws if style references the NORMAL semantic but the point cloud does not have per-point normals', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : '${NORMAL}[0] > 0.5'
|
||
|
|
});
|
||
|
|
expect(function() {
|
||
|
|
scene.renderForSpecs();
|
||
|
|
}).toThrowRuntimeError();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws when shader style reference a non-existent property', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudWithPerPointPropertiesUrl).then(function(tileset) {
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color : 'color() * ${non_existent_property}'
|
||
|
|
});
|
||
|
|
expect(function() {
|
||
|
|
scene.renderForSpecs();
|
||
|
|
}).toThrowRuntimeError();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('does not apply shader style if the point cloud has a batch table', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudBatchedUrl).then(function(tileset) {
|
||
|
|
var content = tileset.root.content;
|
||
|
|
var shaderProgram = content._pointCloud._drawCommand.shaderProgram;
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
color:'color("red")'
|
||
|
|
});
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(content._pointCloud._drawCommand.shaderProgram).toBe(shaderProgram);
|
||
|
|
|
||
|
|
// Point cloud is styled through the batch table
|
||
|
|
expect(scene).notToRender([0, 0, 0, 255]);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('throws when shader style is invalid', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
tileset.style = new Cesium3DTileStyle({
|
||
|
|
show : '1 < "2"'
|
||
|
|
});
|
||
|
|
expect(function() {
|
||
|
|
scene.renderForSpecs();
|
||
|
|
}).toThrowRuntimeError();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('gets memory usage', function() {
|
||
|
|
var promises = [
|
||
|
|
Cesium3DTilesTester.loadTileset(scene, pointCloudNoColorUrl),
|
||
|
|
Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl),
|
||
|
|
Cesium3DTilesTester.loadTileset(scene, pointCloudNormalsUrl),
|
||
|
|
Cesium3DTilesTester.loadTileset(scene, pointCloudQuantizedOctEncodedUrl)
|
||
|
|
];
|
||
|
|
|
||
|
|
// 1000 points
|
||
|
|
var expectedGeometryMemory = [
|
||
|
|
1000 * 12, // 3 floats (xyz)
|
||
|
|
1000 * 15, // 3 floats (xyz), 3 bytes (rgb)
|
||
|
|
1000 * 27, // 3 floats (xyz), 3 bytes (rgb), 3 floats (normal)
|
||
|
|
1000 * 11 // 3 shorts (quantized xyz), 3 bytes (rgb), 2 bytes (oct-encoded normal)
|
||
|
|
];
|
||
|
|
|
||
|
|
return when.all(promises).then(function(tilesets) {
|
||
|
|
var length = tilesets.length;
|
||
|
|
for (var i = 0; i < length; ++i) {
|
||
|
|
var content = tilesets[i].root.content;
|
||
|
|
expect(content.geometryByteLength).toEqual(expectedGeometryMemory[i]);
|
||
|
|
expect(content.texturesByteLength).toEqual(0);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('gets memory usage for batch point cloud', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudBatchedUrl).then(function(tileset) {
|
||
|
|
var content = tileset.root.content;
|
||
|
|
|
||
|
|
// Point cloud consists of positions, colors, normals, and batchIds
|
||
|
|
// 3 floats (xyz), 3 floats (normal), 1 byte (batchId)
|
||
|
|
var pointCloudGeometryMemory = 1000 * 25;
|
||
|
|
|
||
|
|
// One RGBA byte pixel per feature
|
||
|
|
var batchTexturesByteLength = content.featuresLength * 4;
|
||
|
|
var pickTexturesByteLength = content.featuresLength * 4;
|
||
|
|
|
||
|
|
// Features have not been picked or colored yet, so the batch table contribution is 0.
|
||
|
|
expect(content.geometryByteLength).toEqual(pointCloudGeometryMemory);
|
||
|
|
expect(content.texturesByteLength).toEqual(0);
|
||
|
|
expect(content.batchTableByteLength).toEqual(0);
|
||
|
|
|
||
|
|
// Color a feature and expect the texture memory to increase
|
||
|
|
content.getFeature(0).color = Color.RED;
|
||
|
|
scene.renderForSpecs();
|
||
|
|
expect(content.geometryByteLength).toEqual(pointCloudGeometryMemory);
|
||
|
|
expect(content.texturesByteLength).toEqual(0);
|
||
|
|
expect(content.batchTableByteLength).toEqual(batchTexturesByteLength);
|
||
|
|
|
||
|
|
// Pick the tile and expect the texture memory to increase
|
||
|
|
scene.pickForSpecs();
|
||
|
|
expect(content.geometryByteLength).toEqual(pointCloudGeometryMemory);
|
||
|
|
expect(content.texturesByteLength).toEqual(0);
|
||
|
|
expect(content.batchTableByteLength).toEqual(batchTexturesByteLength + pickTexturesByteLength);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('rebuilds shaders when clipping planes are enabled, change between union and intersection, or change count', function () {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
var tile = tileset.root;
|
||
|
|
tile._isClipped = true;
|
||
|
|
var content = tile.content;
|
||
|
|
|
||
|
|
var noClipFS = content._pointCloud._drawCommand.shaderProgram._fragmentShaderText;
|
||
|
|
expect(noClipFS.indexOf('clip') !== -1).toBe(false);
|
||
|
|
|
||
|
|
var clippingPlanes = new ClippingPlaneCollection({
|
||
|
|
planes : [
|
||
|
|
new ClippingPlane(Cartesian3.UNIT_X, 0.0)
|
||
|
|
],
|
||
|
|
unionClippingRegions : false
|
||
|
|
});
|
||
|
|
tileset.clippingPlanes = clippingPlanes;
|
||
|
|
|
||
|
|
clippingPlanes.update(scene.frameState);
|
||
|
|
tile.update(tileset, scene.frameState);
|
||
|
|
var clipOneIntersectFS = content._pointCloud._drawCommand.shaderProgram._fragmentShaderText;
|
||
|
|
expect(clipOneIntersectFS.indexOf('= clip(') !== -1).toBe(true);
|
||
|
|
expect(clipOneIntersectFS.indexOf('float clip') !== -1).toBe(true);
|
||
|
|
|
||
|
|
clippingPlanes.unionClippingRegions = true;
|
||
|
|
|
||
|
|
clippingPlanes.update(scene.frameState);
|
||
|
|
tile.update(tileset, scene.frameState);
|
||
|
|
var clipOneUnionFS = content._pointCloud._drawCommand.shaderProgram._fragmentShaderText;
|
||
|
|
expect(clipOneUnionFS.indexOf('= clip(') !== -1).toBe(true);
|
||
|
|
expect(clipOneUnionFS.indexOf('float clip') !== -1).toBe(true);
|
||
|
|
expect(clipOneUnionFS).not.toEqual(clipOneIntersectFS);
|
||
|
|
|
||
|
|
clippingPlanes.add(new ClippingPlane(Cartesian3.UNIT_Y, 1.0));
|
||
|
|
|
||
|
|
clippingPlanes.update(scene.frameState);
|
||
|
|
tile.update(tileset, scene.frameState);
|
||
|
|
var clipTwoUnionFS = content._pointCloud._drawCommand.shaderProgram._fragmentShaderText;
|
||
|
|
expect(clipTwoUnionFS.indexOf('= clip(') !== -1).toBe(true);
|
||
|
|
expect(clipTwoUnionFS.indexOf('float clip') !== -1).toBe(true);
|
||
|
|
expect(clipTwoUnionFS).not.toEqual(clipOneIntersectFS);
|
||
|
|
expect(clipTwoUnionFS).not.toEqual(clipOneUnionFS);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clipping planes selectively disable rendering', function () {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
var color;
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
color = rgba;
|
||
|
|
});
|
||
|
|
|
||
|
|
var clipPlane = new ClippingPlane(Cartesian3.UNIT_Z, -10.0);
|
||
|
|
tileset.clippingPlanes = new ClippingPlaneCollection({
|
||
|
|
planes : [
|
||
|
|
clipPlane
|
||
|
|
]
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(scene).notToRender(color);
|
||
|
|
|
||
|
|
clipPlane.distance = 0.0;
|
||
|
|
|
||
|
|
expect(scene).toRender(color);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clipping planes apply edge styling', function() {
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
var color;
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
color = rgba;
|
||
|
|
});
|
||
|
|
|
||
|
|
var clipPlane = new ClippingPlane(Cartesian3.UNIT_Z, -10.0);
|
||
|
|
tileset.clippingPlanes = new ClippingPlaneCollection ({
|
||
|
|
planes : [
|
||
|
|
clipPlane
|
||
|
|
],
|
||
|
|
modelMatrix : Transforms.eastNorthUpToFixedFrame(tileset.boundingSphere.center),
|
||
|
|
edgeWidth : 20.0,
|
||
|
|
edgeColor : Color.RED
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(scene).notToRender(color);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clipping planes union regions (Uint8)', function() {
|
||
|
|
// Force uint8 mode - there's a slight rendering difference between
|
||
|
|
// float and packed uint8 clipping planes for this test due to the small context
|
||
|
|
spyOn(ClippingPlaneCollection, 'useFloatTexture').and.returnValue(false);
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
var color;
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
color = rgba;
|
||
|
|
});
|
||
|
|
|
||
|
|
tileset.clippingPlanes = new ClippingPlaneCollection ({
|
||
|
|
planes : [
|
||
|
|
new ClippingPlane(Cartesian3.UNIT_Z, 0.0),
|
||
|
|
new ClippingPlane(Cartesian3.UNIT_X, 0.0)
|
||
|
|
],
|
||
|
|
modelMatrix : Transforms.eastNorthUpToFixedFrame(tileset.boundingSphere.center),
|
||
|
|
unionClippingRegions: true
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(scene).notToRender(color);
|
||
|
|
|
||
|
|
tileset.clippingPlanes.unionClippingRegions = false;
|
||
|
|
|
||
|
|
expect(scene).toRender(color);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('clipping planes union regions (Float)', function() {
|
||
|
|
if (!ClippingPlaneCollection.useFloatTexture(scene.context)) {
|
||
|
|
// This configuration for the test fails in uint8 mode due to the small context
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
return Cesium3DTilesTester.loadTileset(scene, pointCloudRGBUrl).then(function(tileset) {
|
||
|
|
var color;
|
||
|
|
expect(scene).toRenderAndCall(function(rgba) {
|
||
|
|
color = rgba;
|
||
|
|
});
|
||
|
|
|
||
|
|
tileset.clippingPlanes = new ClippingPlaneCollection ({
|
||
|
|
planes : [
|
||
|
|
new ClippingPlane(Cartesian3.UNIT_Z, -10.0),
|
||
|
|
new ClippingPlane(Cartesian3.UNIT_X, 0.0)
|
||
|
|
],
|
||
|
|
modelMatrix : Transforms.eastNorthUpToFixedFrame(tileset.boundingSphere.center),
|
||
|
|
unionClippingRegions: true
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(scene).notToRender(color);
|
||
|
|
|
||
|
|
tileset.clippingPlanes.unionClippingRegions = false;
|
||
|
|
|
||
|
|
expect(scene).toRender(color);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('destroys', function() {
|
||
|
|
return Cesium3DTilesTester.tileDestroys(scene, pointCloudRGBUrl);
|
||
|
|
});
|
||
|
|
|
||
|
|
}, 'WebGL');
|