Parcourir la source

Add FeatureTable

Garrett Johnson il y a 5 ans
Parent
commit
393fab5cc6

+ 3 - 108
src/base/B3DMLoaderBase.js

@@ -1,7 +1,7 @@
 // B3DM File Format
 // https://github.com/CesiumGS/3d-tiles/blob/master/specification/TileFormats/Batched3DModel/README.md
 
-import { arrayToString } from '../utilities/arrayToString.js';
+import { FeatureTable, BatchTable } from '../utilities/FeatureTable.js';
 
 export class B3DMLoaderBase {
 
@@ -58,119 +58,14 @@ export class B3DMLoaderBase {
 
 		// Feature Table
 		const featureTableStart = 28;
-
-		const jsonFeatureTableData = new Uint8Array( buffer, featureTableStart, featureTableJSONByteLength );
-		const jsonFeatureTable = featureTableJSONByteLength === 0 ? {} : JSON.parse( arrayToString( jsonFeatureTableData ) );
-		const featureTable = { ...jsonFeatureTable };
-
-		// const binFeatureTableData = new Uint8Array( buffer, featureTableStart + featureTableJSONByteLength, featureTableBinaryByteLength );
-		// TODO: dereference the json feature table data in to the binary array.
-		// https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/specification/TileFormats/FeatureTable/README.md#json-header
-		// TODO: The feature table contains data with implicit stride and data types, which means we can't parse it into arrays
-		// unless they are specified ahead of time?s
+		const featureTable = new FeatureTable( buffer, featureTableStart, featureTableJSONByteLength, featureTableBinaryByteLength );
 
 		// Batch Table
 		const batchTableStart = featureTableStart + featureTableJSONByteLength + featureTableBinaryByteLength;
-
-		const jsonBatchTableData = new Uint8Array( buffer, batchTableStart, batchTableJSONByteLength );
-		const jsonBatchTable = batchTableJSONByteLength === 0 ? {} : JSON.parse( arrayToString( jsonBatchTableData ) );
-		const batchTable = { ...jsonBatchTable };
-
-		// dereference the json batch table data in to the binary array.
-		// https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/specification/TileFormats/FeatureTable/README.md#json-header
-		// const binBatchTableData = new Uint8Array( buffer, batchTableStart + batchTableJSONByteLength, batchTableBinaryByteLength );
-		const batchLength = jsonFeatureTable.BATCH_LENGTH;
-		for ( const key in jsonBatchTable ) {
-
-			const feature = jsonBatchTable[ key ];
-			if ( Array.isArray( feature ) ) {
-
-				batchTable[ key ] = {
-
-					type: 'SCALAR',
-					stride: 1,
-					data: feature,
-
-				};
-
-			} else {
-
-				let stride;
-				let data;
-				const arrayStart = batchTableStart + batchTableJSONByteLength;
-				const arrayLength = batchLength * stride + feature.byteOffset;
-				switch ( feature.type ) {
-
-					case 'SCALAR':
-						stride = 1;
-						break;
-
-					case 'VEC2':
-						stride = 2;
-						break;
-
-					case 'VEC3':
-						stride = 3;
-						break;
-
-					case 'VEC4':
-						stride = 4;
-						break;
-
-				}
-
-				switch ( feature.componentType ) {
-
-					case 'BYTE':
-						data = new Int8Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'UNSIGNED_BYTE':
-						data = new Uint8Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'SHORT':
-						data = new Int16Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'UNSIGNED_SHORT':
-						data = new Uint16Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'INT':
-						data = new Int32Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'UNSIGNED_INT':
-						data = new Uint32Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'FLOAT':
-						data = new Float32Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'DOUBLE':
-						data = new Float64Array( buffer, arrayStart, arrayLength );
-						break;
-
-				}
-
-				batchTable[ key ] = {
-
-					type: feature.type,
-					stride,
-					data,
-
-				};
-
-			}
-
-		}
+		const batchTable = new BatchTable( buffer, featureTable.getData( 'BATCH_LENGTH' ), batchTableStart, batchTableJSONByteLength, batchTableBinaryByteLength );
 
 		const glbStart = batchTableStart + batchTableJSONByteLength + batchTableBinaryByteLength;
 		const glbBytes = new Uint8Array( buffer, glbStart, byteLength - glbStart );
-		// TODO: Understand how to apply the batchId semantics
-		// https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/specification/TileFormats/Batched3DModel/README.md#binary-gltf
 
 		return {
 			version,

+ 0 - 110
src/base/I3DMLoaderBase.js

@@ -62,115 +62,7 @@ export class I3DMLoaderBase {
 		// Feature Table
 		const featureTableStart = 32;
 
-		const jsonFeatureTableData = new Uint8Array( buffer, featureTableStart, featureTableJSONByteLength );
-		const jsonFeatureTable = featureTableJSONByteLength === 0 ? {} : JSON.parse( arrayToString( jsonFeatureTableData ) );
-		const featureTable = { ...jsonFeatureTable };
-
-		// const binFeatureTableData = new Uint8Array( buffer, featureTableStart + featureTableJSONByteLength, featureTableBinaryByteLength );
-		// TODO: dereference the json feature table data in to the binary array.
-		// https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/specification/TileFormats/FeatureTable/README.md#json-header
-		// TODO: The feature table contains data with implicit stride and data types, which means we can't parse it into arrays
-		// unless they are specified ahead of time?s
-
 		// Batch Table
-		const batchTableStart = featureTableStart + featureTableJSONByteLength + featureTableBinaryByteLength;
-
-		const jsonBatchTableData = new Uint8Array( buffer, batchTableStart, batchTableJSONByteLength );
-		const jsonBatchTable = batchTableJSONByteLength === 0 ? {} : JSON.parse( arrayToString( jsonBatchTableData ) );
-		const batchTable = { ...jsonBatchTable };
-
-		// TODO: Reuse batch and feature table parsers
-
-		// dereference the json batch table data in to the binary array.
-		// https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/specification/TileFormats/FeatureTable/README.md#json-header
-		// const binBatchTableData = new Uint8Array( buffer, batchTableStart + batchTableJSONByteLength, batchTableBinaryByteLength );
-		const batchLength = jsonFeatureTable.BATCH_LENGTH;
-		for ( const key in jsonBatchTable ) {
-
-			const feature = jsonBatchTable[ key ];
-			if ( Array.isArray( feature ) ) {
-
-				batchTable[ key ] = {
-
-					type: 'SCALAR',
-					stride: 1,
-					data: feature,
-
-				};
-
-			} else {
-
-				let stride;
-				let data;
-				const arrayStart = batchTableStart + batchTableJSONByteLength;
-				const arrayLength = batchLength * stride + feature.byteOffset;
-				switch ( feature.type ) {
-
-					case 'SCALAR':
-						stride = 1;
-						break;
-
-					case 'VEC2':
-						stride = 2;
-						break;
-
-					case 'VEC3':
-						stride = 3;
-						break;
-
-					case 'VEC4':
-						stride = 4;
-						break;
-
-				}
-
-				switch ( feature.componentType ) {
-
-					case 'BYTE':
-						data = new Int8Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'UNSIGNED_BYTE':
-						data = new Uint8Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'SHORT':
-						data = new Int16Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'UNSIGNED_SHORT':
-						data = new Uint16Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'INT':
-						data = new Int32Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'UNSIGNED_INT':
-						data = new Uint32Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'FLOAT':
-						data = new Float32Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'DOUBLE':
-						data = new Float64Array( buffer, arrayStart, arrayLength );
-						break;
-
-				}
-
-				batchTable[ key ] = {
-
-					type: feature.type,
-					stride,
-					data,
-
-				};
-
-			}
-
-		}
 
 		const glbStart = batchTableStart + batchTableJSONByteLength + batchTableBinaryByteLength;
 		const bodyBytes = new Uint8Array( buffer, glbStart, byteLength - glbStart );
@@ -188,8 +80,6 @@ export class I3DMLoaderBase {
 
 		}
 
-		// TODO: Understand batch and feature table application
-
 		return {
 			version,
 			featureTable,

+ 2 - 110
src/base/PNTSLoaderBase.js

@@ -1,8 +1,6 @@
 // PNTS File Format
 // https://github.com/CesiumGS/3d-tiles/blob/master/specification/TileFormats/PointCloud/README.md
 
-import { arrayToString } from '../utilities/arrayToString.js';
-
 export class I3DMLoaderBase {
 
 	constructor() {
@@ -59,117 +57,11 @@ export class I3DMLoaderBase {
 		// Feature Table
 		const featureTableStart = 28;
 
-		const jsonFeatureTableData = new Uint8Array( buffer, featureTableStart, featureTableJSONByteLength );
-		const jsonFeatureTable = featureTableJSONByteLength === 0 ? {} : JSON.parse( arrayToString( jsonFeatureTableData ) );
-		const featureTable = { ...jsonFeatureTable };
-
-		// const binFeatureTableData = new Uint8Array( buffer, featureTableStart + featureTableJSONByteLength, featureTableBinaryByteLength );
-		// TODO: dereference the json feature table data in to the binary array.
-		// https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/specification/TileFormats/FeatureTable/README.md#json-header
-		// TODO: The feature table contains data with implicit stride and data types, which means we can't parse it into arrays
-		// unless they are specified ahead of time?s
+		// TODO
 
 		// Batch Table
-		const batchTableStart = featureTableStart + featureTableJSONByteLength + featureTableBinaryByteLength;
-
-		const jsonBatchTableData = new Uint8Array( buffer, batchTableStart, batchTableJSONByteLength );
-		const jsonBatchTable = batchTableJSONByteLength === 0 ? {} : JSON.parse( arrayToString( jsonBatchTableData ) );
-		const batchTable = { ...jsonBatchTable };
-
-		// TODO: Reuse batch and feature table parsers
-
-		// dereference the json batch table data in to the binary array.
-		// https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/specification/TileFormats/FeatureTable/README.md#json-header
-		// const binBatchTableData = new Uint8Array( buffer, batchTableStart + batchTableJSONByteLength, batchTableBinaryByteLength );
-		const batchLength = jsonFeatureTable.BATCH_LENGTH;
-		for ( const key in jsonBatchTable ) {
-
-			const feature = jsonBatchTable[ key ];
-			if ( Array.isArray( feature ) ) {
-
-				batchTable[ key ] = {
-
-					type: 'SCALAR',
-					stride: 1,
-					data: feature,
-
-				};
-
-			} else {
-
-				let stride;
-				let data;
-				const arrayStart = batchTableStart + batchTableJSONByteLength;
-				const arrayLength = batchLength * stride + feature.byteOffset;
-				switch ( feature.type ) {
-
-					case 'SCALAR':
-						stride = 1;
-						break;
-
-					case 'VEC2':
-						stride = 2;
-						break;
-
-					case 'VEC3':
-						stride = 3;
-						break;
-
-					case 'VEC4':
-						stride = 4;
-						break;
-
-				}
-
-				switch ( feature.componentType ) {
-
-					case 'BYTE':
-						data = new Int8Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'UNSIGNED_BYTE':
-						data = new Uint8Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'SHORT':
-						data = new Int16Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'UNSIGNED_SHORT':
-						data = new Uint16Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'INT':
-						data = new Int32Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'UNSIGNED_INT':
-						data = new Uint32Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'FLOAT':
-						data = new Float32Array( buffer, arrayStart, arrayLength );
-						break;
-
-					case 'DOUBLE':
-						data = new Float64Array( buffer, arrayStart, arrayLength );
-						break;
-
-				}
-
-				batchTable[ key ] = {
-
-					type: feature.type,
-					stride,
-					data,
-
-				};
-
-			}
-
-		}
 
-		// TODO: Understand batch and feature table application
+		// TODO
 
 		return {
 			version,

+ 142 - 0
src/utilities/FeatureTable.js

@@ -0,0 +1,142 @@
+import { arrayToString } from './arrayToString.js';
+
+export class FeatureTable {
+
+	constructor( buffer, start, headerLength, binLength ) {
+
+		this.buffer = buffer;
+		this.binOffset = start + headerLength;
+		this.binLength = binLength;
+
+		let header = null;
+		if ( headerLength !== 0 ) {
+
+			const headerData = new Uint8Array( buffer, start, headerLength );
+			header = JSON.parse( arrayToString( headerData ) );
+
+		} else {
+
+			header = {};
+
+		}
+		this.header = header;
+
+	}
+
+	getKeys() {
+
+		return Object.keys( this.header );
+
+	}
+
+	getData( key, count, type = null, componentType = null ) {
+
+		const header = this.header;
+		const feature = header[ key ];
+		if ( ! ( feature instanceof Object ) ) {
+
+			return feature;
+
+		} else if ( Array.isArray( feature ) ) {
+
+			return feature;
+
+		} else {
+
+			const { buffer, binOffset, binLength } = this;
+			const byteOffset = feature.byteOffset || 0;
+			const featureType = type || feature.type;
+			const featureComponentType = componentType || feature.componentType;
+
+			let stride;
+			switch ( featureType ) {
+
+				case 'SCALAR':
+					stride = 1;
+					break;
+
+				case 'VEC2':
+					stride = 2;
+					break;
+
+				case 'VEC3':
+					stride = 3;
+					break;
+
+				case 'VEC4':
+					stride = 4;
+					break;
+
+			}
+
+			let data;
+			const arrayStart = binOffset + byteOffset;
+			const arrayLength = count * stride;
+
+			switch ( featureComponentType ) {
+
+				case 'BYTE':
+					data = new Int8Array( buffer, arrayStart, arrayLength );
+					break;
+
+				case 'UNSIGNED_BYTE':
+					data = new Uint8Array( buffer, arrayStart, arrayLength );
+					break;
+
+				case 'SHORT':
+					data = new Int16Array( buffer, arrayStart, arrayLength );
+					break;
+
+				case 'UNSIGNED_SHORT':
+					data = new Uint16Array( buffer, arrayStart, arrayLength );
+					break;
+
+				case 'INT':
+					data = new Int32Array( buffer, arrayStart, arrayLength );
+					break;
+
+				case 'UNSIGNED_INT':
+					data = new Uint32Array( buffer, arrayStart, arrayLength );
+					break;
+
+				case 'FLOAT':
+					data = new Float32Array( buffer, arrayStart, arrayLength );
+					break;
+
+				case 'DOUBLE':
+					data = new Float64Array( buffer, arrayStart, arrayLength );
+					break;
+
+			}
+
+			const dataEnd = arrayStart + arrayLength * data.BYTES_PER_ELEMENT;
+			if ( dataEnd > binOffset + binLength ) {
+
+				throw new Error( 'FeatureTable: Feature data read outside binary body length.' );
+
+			}
+
+			return data;
+
+		}
+
+	}
+
+}
+
+export class BatchTable extends FeatureTable {
+
+	constructor( buffer, batchSize, start, headerLength, binLength ) {
+
+		super( buffer, start, headerLength, binLength );
+		this.batchSize = batchSize;
+
+	}
+
+	getData( key, type = null, componentType = null ) {
+
+		return this.getData( key, this.batchSize, type, componentType );
+
+	}
+
+}

+ 0 - 1
src/utilities/parseBatchTable.js

@@ -1 +0,0 @@
-function parseBatchTable( header, body ) {}