Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3D Tiles - Support batch table binary #4228

Merged
merged 4 commits into from
Aug 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Apps/Sandcastle/gallery/3D Tiles.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
name : 'PointsConstantColor', url : '../../../Specs/Data/Cesium3DTiles/Points/PointsConstantColor/'
}, {
name : 'PointsNormals', url : '../../../Specs/Data/Cesium3DTiles/Points/PointsQuantizedOctEncoded/'
}, {
name : 'PointsBatched', url : '../../../Specs/Data/Cesium3DTiles/Points/PointsBatched/'
}];

var tileset;
Expand Down
31 changes: 31 additions & 0 deletions Source/Core/ComponentDatatype.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,5 +297,36 @@ define([
}
};

/**
* Get the ComponentDatatype from its name.
*
* @param {String} name The name of the ComponentDatatype.
* @returns {ComponentDatatype} The ComponentDatatype.
*
* @exception {DeveloperError} name is not a valid value.
*/
ComponentDatatype.fromName = function(name) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add to CHANGES.md since this is a public class.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also cherry-pick this into master.

switch (name) {
case 'BYTE':
return ComponentDatatype.BYTE;
case 'UNSIGNED_BYTE':
return ComponentDatatype.UNSIGNED_BYTE;
case 'SHORT':
return ComponentDatatype.SHORT;
case 'UNSIGNED_SHORT':
return ComponentDatatype.UNSIGNED_SHORT;
case 'INT':
return ComponentDatatype.INT;
case 'UNSIGNED_INT':
return ComponentDatatype.UNSIGNED_INT;
case 'FLOAT':
return ComponentDatatype.FLOAT;
case 'DOUBLE':
return ComponentDatatype.DOUBLE;
default:
throw new DeveloperError('name is not a valid value.');
}
};

return freezeObject(ComponentDatatype);
});
73 changes: 50 additions & 23 deletions Source/Scene/Batched3DModel3DTileContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ define([
'../Core/RequestType',
'../ThirdParty/when',
'./Cesium3DTileFeature',
'./Cesium3DTileBatchTableResources',
'./Cesium3DTileBatchTable',
'./Cesium3DTileContentState',
'./Model'
], function(
Expand All @@ -32,7 +32,7 @@ define([
RequestType,
when,
Cesium3DTileFeature,
Cesium3DTileBatchTableResources,
Cesium3DTileBatchTable,
Cesium3DTileContentState,
Model) {
'use strict';
Expand All @@ -57,7 +57,7 @@ define([
* The following properties are part of the {@link Cesium3DTileContent} interface.
*/
this.state = Cesium3DTileContentState.UNLOADED;
this.batchTableResources = undefined;
this.batchTable = undefined;
this.featurePropertiesDirty = false;

this._contentReadyToProcessPromise = when.defer();
Expand Down Expand Up @@ -120,7 +120,7 @@ define([
* Part of the {@link Cesium3DTileContent} interface.
*/
Batched3DModel3DTileContent.prototype.hasProperty = function(name) {
return this.batchTableResources.hasProperty(name);
return this.batchTable.hasProperty(name);
};

/**
Expand Down Expand Up @@ -199,27 +199,54 @@ define([
var byteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint32;

var batchLength = view.getUint32(byteOffset, true);
this._featuresLength = batchLength;
var batchTableJsonByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint32;

var batchTableResources = new Cesium3DTileBatchTableResources(this, batchLength);
this.batchTableResources = batchTableResources;
var batchTableBinaryByteLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint32;

var batchTableByteLength = view.getUint32(byteOffset, true);
var batchLength = view.getUint32(byteOffset, true);
byteOffset += sizeOfUint32;
if (batchTableByteLength > 0) {
var batchTableString = getStringFromTypedArray(uint8Array, byteOffset, batchTableByteLength);
byteOffset += batchTableByteLength;

// TODO : remove this legacy check before merging into master
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lilleyse when this is merged, can you also email the forum about this small breaking change for b3dm?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

// Legacy header: [batchLength] [batchTableByteLength]
// Current header: [batchTableJsonByteLength] [batchTableBinaryByteLength] [batchLength]
// If the header is in the legacy format 'batchLength' will be the start of the JSON string (a quotation mark) or the glTF magic.
// Accordingly the first byte of uint32 will be either 0x22 or 0x67 and so the uint32 will exceed any reasonable 'batchLength'.
if (batchLength > 10000000) {
byteOffset -= sizeOfUint32;
batchLength = batchTableJsonByteLength;
batchTableJsonByteLength = batchTableBinaryByteLength;
batchTableBinaryByteLength = 0;
console.log('Warning: b3dm header is using the legacy format [batchLength] [batchTableByteLength]. The new format is [batchTableJsonByteLength] [batchTableBinaryByteLength] [batchLength] from https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/TileFormats/Batched3DModel/README.md.');
}

this._featuresLength = batchLength;

var batchTableJson;
var batchTableBinary;
if (batchTableJsonByteLength > 0) {
// PERFORMANCE_IDEA: is it possible to allocate this on-demand? Perhaps keep the
// arraybuffer/string compressed in memory and then decompress it when it is first accessed.
//
// We could also make another request for it, but that would make the property set/get
// API async, and would double the number of numbers in some cases.
batchTableResources.batchTable = JSON.parse(batchTableString);
var batchTableString = getStringFromTypedArray(uint8Array, byteOffset, batchTableJsonByteLength);
batchTableJson = JSON.parse(batchTableString);
byteOffset += batchTableJsonByteLength;

if (batchTableBinaryByteLength > 0) {
// Has a batch table binary
batchTableBinary = new Uint8Array(arrayBuffer, byteOffset, batchTableBinaryByteLength);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how the GC works, but I wonder if holding on to this subset of the original arrayBuffer forces the GC to keep the entire arrayBuffer in memory. @shunter do you know?

// Copy the batchTableBinary section and let the underlying ArrayBuffer be freed
batchTableBinary = new Uint8Array(batchTableBinary);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does any part of Model.js need to change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No

byteOffset += batchTableBinaryByteLength;
}
}

var batchTable = new Cesium3DTileBatchTable(this, batchLength, batchTableJson, batchTableBinary);
this.batchTable = batchTable;

var gltfByteLength = byteStart + byteLength - byteOffset;
var gltfView = new Uint8Array(arrayBuffer, byteOffset, gltfByteLength);

Expand All @@ -231,12 +258,12 @@ define([
releaseGltfJson : true, // Models are unique and will not benefit from caching so save memory
basePath : this._url,
modelMatrix : this._tile.computedTransform,
vertexShaderLoaded : batchTableResources.getVertexShaderCallback(),
fragmentShaderLoaded : batchTableResources.getFragmentShaderCallback(),
uniformMapLoaded : batchTableResources.getUniformMapCallback(),
pickVertexShaderLoaded : batchTableResources.getPickVertexShaderCallback(),
pickFragmentShaderLoaded : batchTableResources.getPickFragmentShaderCallback(),
pickUniformMapLoaded : batchTableResources.getPickUniformMapCallback()
vertexShaderLoaded : batchTable.getVertexShaderCallback(),
fragmentShaderLoaded : batchTable.getFragmentShaderCallback(),
uniformMapLoaded : batchTable.getUniformMapCallback(),
pickVertexShaderLoaded : batchTable.getPickVertexShaderCallback(),
pickFragmentShaderLoaded : batchTable.getPickFragmentShaderCallback(),
pickUniformMapLoaded : batchTable.getPickUniformMapCallback()
});

this._model = model;
Expand All @@ -259,7 +286,7 @@ define([
*/
Batched3DModel3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
color = enabled ? color : Color.WHITE;
this.batchTableResources.setAllColor(color);
this.batchTable.setAllColor(color);
};

/**
Expand All @@ -268,13 +295,13 @@ define([
Batched3DModel3DTileContent.prototype.update = function(tileset, frameState) {
var oldAddCommand = frameState.addCommand;
if (frameState.passes.render) {
frameState.addCommand = this.batchTableResources.getAddCommand();
frameState.addCommand = this.batchTable.getAddCommand();
}

// In the PROCESSING state we may be calling update() to move forward
// the content's resource loading. In the READY state, it will
// actually generate commands.
this.batchTableResources.update(tileset, frameState);
this.batchTable.update(tileset, frameState);
this._model.update(frameState);

frameState.addCommand = oldAddCommand;
Expand All @@ -292,7 +319,7 @@ define([
*/
Batched3DModel3DTileContent.prototype.destroy = function() {
this._model = this._model && this._model.destroy();
this.batchTableResources = this.batchTableResources && this.batchTableResources.destroy();
this.batchTable = this.batchTable && this.batchTable.destroy();

return destroyObject(this);
};
Expand Down
Loading