DSDSWeb/static/js/Cesium-1.53/Specs/Scene/Batched3DModel3DTileContent...

382 lines
16 KiB
JavaScript
Raw Normal View History

2024-07-11 18:02:47 +08:00
defineSuite([
'Scene/Batched3DModel3DTileContent',
'Core/Cartesian3',
'Core/Color',
'Core/HeadingPitchRange',
'Core/HeadingPitchRoll',
'Core/Matrix4',
'Core/Transforms',
'Scene/ClippingPlane',
'Scene/ClippingPlaneCollection',
'Scene/Model',
'Specs/Cesium3DTilesTester',
'Specs/createScene'
], function(
Batched3DModel3DTileContent,
Cartesian3,
Color,
HeadingPitchRange,
HeadingPitchRoll,
Matrix4,
Transforms,
ClippingPlane,
ClippingPlaneCollection,
Model,
Cesium3DTilesTester,
createScene) {
'use strict';
var scene;
var centerLongitude = -1.31968;
var centerLatitude = 0.698874;
var withBatchTableUrl = './Data/Cesium3DTiles/Batched/BatchedWithBatchTable/tileset.json';
var withBatchTableBinaryUrl = './Data/Cesium3DTiles/Batched/BatchedWithBatchTableBinary/tileset.json';
var withoutBatchTableUrl = './Data/Cesium3DTiles/Batched/BatchedWithoutBatchTable/tileset.json';
var translucentUrl = './Data/Cesium3DTiles/Batched/BatchedTranslucent/tileset.json';
var translucentOpaqueMixUrl = './Data/Cesium3DTiles/Batched/BatchedTranslucentOpaqueMix/tileset.json';
var withTransformBoxUrl = './Data/Cesium3DTiles/Batched/BatchedWithTransformBox/tileset.json';
var withTransformSphereUrl = './Data/Cesium3DTiles/Batched/BatchedWithTransformSphere/tileset.json';
var withTransformRegionUrl = './Data/Cesium3DTiles/Batched/BatchedWithTransformRegion/tileset.json';
var texturedUrl = './Data/Cesium3DTiles/Batched/BatchedTextured/tileset.json';
var deprecated1Url = './Data/Cesium3DTiles/Batched/BatchedDeprecated1/tileset.json';
var deprecated2Url = './Data/Cesium3DTiles/Batched/BatchedDeprecated2/tileset.json';
var withRtcCenterUrl = './Data/Cesium3DTiles/Batched/BatchedWithRtcCenter/tileset.json';
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));
}
beforeAll(function() {
scene = createScene();
// Keep the error from logging to the console when running tests
spyOn(Batched3DModel3DTileContent, '_deprecationWarning');
});
afterAll(function() {
scene.destroyForSpecs();
});
beforeEach(function() {
setCamera(centerLongitude, centerLatitude);
});
afterEach(function() {
scene.primitives.removeAll();
});
it('throws with invalid version', function() {
var arrayBuffer = Cesium3DTilesTester.generateBatchedTileBuffer({
version : 2
});
Cesium3DTilesTester.loadTileExpectError(scene, arrayBuffer, 'b3dm');
});
it('recognizes the legacy 20-byte header', function() {
return Cesium3DTilesTester.loadTileset(scene, deprecated1Url)
.then(function(tileset) {
expect(Batched3DModel3DTileContent._deprecationWarning).toHaveBeenCalled();
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
var batchTable = tileset.root.content.batchTable;
expect(batchTable._properties).toBeDefined();
});
});
it('recognizes the legacy 24-byte header', function() {
return Cesium3DTilesTester.loadTileset(scene, deprecated2Url)
.then(function(tileset) {
expect(Batched3DModel3DTileContent._deprecationWarning).toHaveBeenCalled();
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
var batchTable = tileset.root.content.batchTable;
expect(batchTable._properties).toBeDefined();
});
});
it('logs deprecation warning for use of BATCHID without prefixed underscore', function() {
return Cesium3DTilesTester.loadTileset(scene, deprecated1Url)
.then(function(tileset) {
expect(Batched3DModel3DTileContent._deprecationWarning).toHaveBeenCalled();
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
});
});
it('throws with empty gltf', function() {
// Expect to throw DeveloperError in Model due to invalid gltf magic
var arrayBuffer = Cesium3DTilesTester.generateBatchedTileBuffer();
Cesium3DTilesTester.loadTileExpectError(scene, arrayBuffer, 'b3dm');
});
it('resolves readyPromise', function() {
return Cesium3DTilesTester.resolvesReadyPromise(scene, withoutBatchTableUrl);
});
it('renders with batch table', function() {
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
});
});
it('renders with batch table binary', function() {
return Cesium3DTilesTester.loadTileset(scene, withBatchTableBinaryUrl).then(function(tileset) {
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
});
});
it('renders without batch table', function() {
return Cesium3DTilesTester.loadTileset(scene, withoutBatchTableUrl).then(function(tileset) {
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
});
});
it('renders with all features translucent', function() {
return Cesium3DTilesTester.loadTileset(scene, translucentUrl).then(function(tileset) {
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
});
});
it('renders with a mix of opaque and translucent features', function() {
return Cesium3DTilesTester.loadTileset(scene, translucentOpaqueMixUrl).then(function(tileset) {
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
});
});
it('renders with textures', function() {
return Cesium3DTilesTester.loadTileset(scene, texturedUrl).then(function(tileset) {
Cesium3DTilesTester.expectRender(scene, tileset);
});
});
function expectRenderWithTransform(url) {
return Cesium3DTilesTester.loadTileset(scene, url).then(function(tileset) {
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
var newLongitude = -1.31962;
var newLatitude = 0.698874;
var newCenter = Cartesian3.fromRadians(newLongitude, newLatitude, 0.0);
var newHPR = new HeadingPitchRoll();
var newTransform = Transforms.headingPitchRollToFixedFrame(newCenter, newHPR);
// Update tile transform
tileset.root.transform = newTransform;
scene.renderForSpecs();
// Move the camera to the new location
setCamera(newLongitude, newLatitude);
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
});
}
it('renders with a tile transform and box bounding volume', function() {
return expectRenderWithTransform(withTransformBoxUrl);
});
it('renders with a tile transform and sphere bounding volume', function() {
return expectRenderWithTransform(withTransformSphereUrl);
});
it('renders with a tile transform and region bounding volume', function() {
return expectRenderWithTransform(withTransformRegionUrl);
});
it('picks with batch table', function() {
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).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 without batch table', function() {
return Cesium3DTilesTester.loadTileset(scene, withoutBatchTableUrl).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('can get features and properties', function() {
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
var content = tileset.root.content;
expect(content.featuresLength).toBe(10);
expect(content.innerContents).toBeUndefined();
expect(content.hasProperty(0, 'id')).toBe(true);
expect(content.getFeature(0)).toBeDefined();
});
});
it('throws when calling getFeature with invalid index', function() {
return Cesium3DTilesTester.loadTileset(scene, withoutBatchTableUrl).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('gets memory usage', function() {
return Cesium3DTilesTester.loadTileset(scene, texturedUrl).then(function(tileset) {
var content = tileset.root.content;
// 10 buildings, 36 ushort indices and 24 vertices per building, 8 float components (position, normal, uv) and 1 uint component (batchId) per vertex.
// 10 * ((24 * (8 * 4 + 1 * 4)) + (36 * 2)) = 9360
var geometryByteLength = 9360;
// Texture is 128x128 RGBA bytes, not mipmapped
var texturesByteLength = 65536;
// 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(geometryByteLength);
expect(content.texturesByteLength).toEqual(texturesByteLength);
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(geometryByteLength);
expect(content.texturesByteLength).toEqual(texturesByteLength);
expect(content.batchTableByteLength).toEqual(batchTexturesByteLength);
// Pick the tile and expect the texture memory to increase
scene.pickForSpecs();
expect(content.geometryByteLength).toEqual(geometryByteLength);
expect(content.texturesByteLength).toEqual(texturesByteLength);
expect(content.batchTableByteLength).toEqual(batchTexturesByteLength + pickTexturesByteLength);
});
});
it('Links model to tileset clipping planes based on bounding volume clipping', function() {
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
var tile = tileset.root;
var content = tile.content;
var model = content._model;
expect(model.clippingPlanes).toBeUndefined();
var clippingPlaneCollection = new ClippingPlaneCollection({
planes : [
new ClippingPlane(Cartesian3.UNIT_X, 0.0)
]
});
tileset.clippingPlanes = clippingPlaneCollection;
clippingPlaneCollection.update(scene.frameState);
tile.update(tileset, scene.frameState);
expect(model.clippingPlanes).toBeDefined();
expect(model.clippingPlanes).toBe(tileset.clippingPlanes);
tile._isClipped = false;
tile.update(tileset, scene.frameState);
expect(model.clippingPlanes).toBeUndefined();
});
});
it('Links model to tileset clipping planes if tileset clipping planes are reassigned', function() {
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
var tile = tileset.root;
var model = tile.content._model;
expect(model.clippingPlanes).toBeUndefined();
var clippingPlaneCollection = new ClippingPlaneCollection({
planes : [
new ClippingPlane(Cartesian3.UNIT_X, 0.0)
]
});
tileset.clippingPlanes = clippingPlaneCollection;
clippingPlaneCollection.update(scene.frameState);
tile.update(tileset, scene.frameState);
expect(model.clippingPlanes).toBeDefined();
expect(model.clippingPlanes).toBe(tileset.clippingPlanes);
var newClippingPlaneCollection = new ClippingPlaneCollection({
planes : [
new ClippingPlane(Cartesian3.UNIT_X, 0.0)
]
});
tileset.clippingPlanes = newClippingPlaneCollection;
newClippingPlaneCollection.update(scene.frameState);
expect(model.clippingPlanes).not.toBe(tileset.clippingPlanes);
tile.update(tileset, scene.frameState);
expect(model.clippingPlanes).toBe(tileset.clippingPlanes);
});
});
it('rebuilds Model shaders when clipping planes change', function() {
spyOn(Model, '_getClippingFunction').and.callThrough();
return Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl).then(function(tileset) {
var tile = tileset.root;
var clippingPlaneCollection = new ClippingPlaneCollection({
planes : [
new ClippingPlane(Cartesian3.UNIT_X, 0.0)
]
});
tileset.clippingPlanes = clippingPlaneCollection;
clippingPlaneCollection.update(scene.frameState);
tile.update(tileset, scene.frameState);
expect(Model._getClippingFunction.calls.count()).toEqual(1);
});
});
it('transforms model positions by RTC_CENTER property in the features table', function() {
return Cesium3DTilesTester.loadTileset(scene, withRtcCenterUrl).then(function(tileset) {
Cesium3DTilesTester.expectRenderTileset(scene, tileset);
var rtcTransform = tileset.root.content._rtcCenterTransform;
expect(rtcTransform).toEqual(Matrix4.fromTranslation(new Cartesian3(0.1, 0.2, 0.3)));
var expectedModelTransform = Matrix4.multiply(tileset.root.transform, rtcTransform, new Matrix4());
expect(tileset.root.content._contentModelMatrix).toEqual(expectedModelTransform);
expect(tileset.root.content._model._modelMatrix).toEqual(expectedModelTransform);
// Update tile transform
var newLongitude = -1.31962;
var newLatitude = 0.698874;
var newCenter = Cartesian3.fromRadians(newLongitude, newLatitude, 0.0);
var newHPR = new HeadingPitchRoll();
var newTransform = Transforms.headingPitchRollToFixedFrame(newCenter, newHPR);
tileset.root.transform = newTransform;
scene.camera.lookAt(newCenter, new HeadingPitchRange(0.0, 0.0, 15.0));
scene.renderForSpecs();
expectedModelTransform = Matrix4.multiply(tileset.root.computedTransform, rtcTransform, expectedModelTransform);
expect(tileset.root.content._model._modelMatrix).toEqual(expectedModelTransform);
});
});
it('destroys', function() {
return Cesium3DTilesTester.tileDestroys(scene, withoutBatchTableUrl);
});
}, 'WebGL');