Browse Source

PCDLoader: implement binary PCD data type parsing (#31061)

* feat: implement binary PCD data type parsing

* chore: code format

* chore: add verification file

* chore: add file select widget

* fix: destroy gui
徒言 9 months ago
parent
commit
3a21dee9cd

+ 86 - 14
examples/jsm/loaders/PCDLoader.js

@@ -97,6 +97,71 @@ class PCDLoader extends Loader {
 
 	}
 
+	/**
+	 * Get dataview value by field type and size.
+	 *
+	 * @param {DataView} dataview - The DataView to read from.
+	 * @param {number} offset - The offset to start reading from.
+	 * @param {'F' | 'U' | 'I'} type - Field type.
+	 * @param {number} size - Field size.
+	 * @returns {number} Field value.
+	 */
+	_getDataView( dataview, offset, type, size ) {
+
+		switch ( type ) {
+
+			case 'F': {
+
+				if ( size === 8 ) {
+
+					return dataview.getFloat64( offset, this.littleEndian );
+
+				}
+
+				return dataview.getFloat32( offset, this.littleEndian );
+
+			}
+
+			case 'I': {
+
+				if ( size === 1 ) {
+
+					return dataview.getInt8( offset );
+
+				}
+
+				if ( size === 2 ) {
+
+					return dataview.getInt16( offset, this.littleEndian );
+
+				}
+
+				return dataview.getInt32( offset, this.littleEndian );
+
+			}
+
+			case 'U': {
+
+				if ( size === 1 ) {
+
+					return dataview.getUint8( offset );
+
+				}
+
+				if ( size === 2 ) {
+
+					return dataview.getUint16( offset, this.littleEndian );
+
+				}
+
+				return dataview.getUint32( offset, this.littleEndian );
+
+			}
+
+		}
+
+	}
+
 	/**
 	 * Parses the given PCD data and returns a point cloud.
 	 *
@@ -381,9 +446,9 @@ class PCDLoader extends Loader {
 					const xIndex = PCDheader.fields.indexOf( 'x' );
 					const yIndex = PCDheader.fields.indexOf( 'y' );
 					const zIndex = PCDheader.fields.indexOf( 'z' );
-					position.push( dataview.getFloat32( ( PCDheader.points * offset.x ) + PCDheader.size[ xIndex ] * i, this.littleEndian ) );
-					position.push( dataview.getFloat32( ( PCDheader.points * offset.y ) + PCDheader.size[ yIndex ] * i, this.littleEndian ) );
-					position.push( dataview.getFloat32( ( PCDheader.points * offset.z ) + PCDheader.size[ zIndex ] * i, this.littleEndian ) );
+					position.push( this._getDataView( dataview, ( PCDheader.points * offset.x ) + PCDheader.size[ xIndex ] * i, PCDheader.type[ xIndex ], PCDheader.size[ xIndex ] ) );
+					position.push( this._getDataView( dataview, ( PCDheader.points * offset.y ) + PCDheader.size[ yIndex ] * i, PCDheader.type[ yIndex ], PCDheader.size[ yIndex ] ) );
+					position.push( this._getDataView( dataview, ( PCDheader.points * offset.z ) + PCDheader.size[ zIndex ] * i, PCDheader.type[ zIndex ], PCDheader.size[ zIndex ] ) );
 
 				}
 
@@ -406,16 +471,16 @@ class PCDLoader extends Loader {
 					const xIndex = PCDheader.fields.indexOf( 'normal_x' );
 					const yIndex = PCDheader.fields.indexOf( 'normal_y' );
 					const zIndex = PCDheader.fields.indexOf( 'normal_z' );
-					normal.push( dataview.getFloat32( ( PCDheader.points * offset.normal_x ) + PCDheader.size[ xIndex ] * i, this.littleEndian ) );
-					normal.push( dataview.getFloat32( ( PCDheader.points * offset.normal_y ) + PCDheader.size[ yIndex ] * i, this.littleEndian ) );
-					normal.push( dataview.getFloat32( ( PCDheader.points * offset.normal_z ) + PCDheader.size[ zIndex ] * i, this.littleEndian ) );
+					normal.push( this._getDataView( dataview, ( PCDheader.points * offset.normal_x ) + PCDheader.size[ xIndex ] * i, PCDheader.type[ xIndex ], PCDheader.size[ xIndex ] ) );
+					normal.push( this._getDataView( dataview, ( PCDheader.points * offset.normal_y ) + PCDheader.size[ yIndex ] * i, PCDheader.type[ yIndex ], PCDheader.size[ yIndex ] ) );
+					normal.push( this._getDataView( dataview, ( PCDheader.points * offset.normal_z ) + PCDheader.size[ zIndex ] * i, PCDheader.type[ zIndex ], PCDheader.size[ zIndex ] ) );
 
 				}
 
 				if ( offset.intensity !== undefined ) {
 
 					const intensityIndex = PCDheader.fields.indexOf( 'intensity' );
-					intensity.push( dataview.getFloat32( ( PCDheader.points * offset.intensity ) + PCDheader.size[ intensityIndex ] * i, this.littleEndian ) );
+					intensity.push( this._getDataView( dataview, ( PCDheader.points * offset.intensity ) + PCDheader.size[ intensityIndex ] * i, PCDheader.type[ intensityIndex ], PCDheader.size[ intensityIndex ] ) );
 
 				}
 
@@ -441,9 +506,12 @@ class PCDLoader extends Loader {
 
 				if ( offset.x !== undefined ) {
 
-					position.push( dataview.getFloat32( row + offset.x, this.littleEndian ) );
-					position.push( dataview.getFloat32( row + offset.y, this.littleEndian ) );
-					position.push( dataview.getFloat32( row + offset.z, this.littleEndian ) );
+					const xIndex = PCDheader.fields.indexOf( 'x' );
+					const yIndex = PCDheader.fields.indexOf( 'y' );
+					const zIndex = PCDheader.fields.indexOf( 'z' );
+					position.push( this._getDataView( dataview, row + offset.x, PCDheader.type[ xIndex ], PCDheader.size[ xIndex ] ) );
+					position.push( this._getDataView( dataview, row + offset.y, PCDheader.type[ yIndex ], PCDheader.size[ yIndex ] ) );
+					position.push( this._getDataView( dataview, row + offset.z, PCDheader.type[ zIndex ], PCDheader.size[ zIndex ] ) );
 
 				}
 
@@ -461,15 +529,19 @@ class PCDLoader extends Loader {
 
 				if ( offset.normal_x !== undefined ) {
 
-					normal.push( dataview.getFloat32( row + offset.normal_x, this.littleEndian ) );
-					normal.push( dataview.getFloat32( row + offset.normal_y, this.littleEndian ) );
-					normal.push( dataview.getFloat32( row + offset.normal_z, this.littleEndian ) );
+					const xIndex = PCDheader.fields.indexOf( 'normal_x' );
+					const yIndex = PCDheader.fields.indexOf( 'normal_y' );
+					const zIndex = PCDheader.fields.indexOf( 'normal_z' );
+					normal.push( this._getDataView( dataview, row + offset.normal_x, PCDheader.type[ xIndex ], PCDheader.size[ xIndex ] ) );
+					normal.push( this._getDataView( dataview, row + offset.normal_y, PCDheader.type[ yIndex ], PCDheader.size[ yIndex ] ) );
+					normal.push( this._getDataView( dataview, row + offset.normal_z, PCDheader.type[ zIndex ], PCDheader.size[ zIndex ] ) );
 
 				}
 
 				if ( offset.intensity !== undefined ) {
 
-					intensity.push( dataview.getFloat32( row + offset.intensity, this.littleEndian ) );
+					const intensityIndex = PCDheader.fields.indexOf( 'intensity' );
+					intensity.push( this._getDataView( dataview, row + offset.intensity, PCDheader.type[ intensityIndex ], PCDheader.size[ intensityIndex ] ) );
 
 				}
 

BIN
examples/models/pcd/binary/Zaghetto_8bit.pcd


+ 28 - 13
examples/webgl_loader_pcd.html

@@ -55,26 +55,41 @@
 				//scene.add( new THREE.AxesHelper( 1 ) );
 
 				const loader = new PCDLoader();
-				loader.load( './models/pcd/binary/Zaghetto.pcd', function ( points ) {
 
-					points.geometry.center();
-					points.geometry.rotateX( Math.PI );
-					points.name = 'Zaghetto.pcd';
-					scene.add( points );
+				const loadPointCloud = function ( file ) {
 
-					//
+					loader.load( './models/pcd/' + file, function ( points ) {
 
-					const gui = new GUI();
+						points.geometry.center();
+						points.geometry.rotateX( Math.PI );
+						points.name = file;
+						scene.add( points );
 
-					gui.add( points.material, 'size', 0.001, 0.01 ).onChange( render );
-					gui.addColor( points.material, 'color' ).onChange( render );
-					gui.open();
+						const gui = new GUI();
 
-					//
+						gui.add( points.material, 'size', 0.001, 0.01 ).onChange( render );
+						gui.addColor( points.material, 'color' ).onChange( render );
+						gui.add( points, 'name', [
+							'ascii/simple.pcd',
+							'binary/Zaghetto.pcd',
+							'binary/Zaghetto_8bit.pcd',
+							'binary_compressed/pcl_logo.pcd',
+						] ).name( 'type' ).onChange( e => {
 
-					render();
+							gui.destroy();
+							scene.remove( points );
+							loadPointCloud( e );
+			
+						} );
+						gui.open();
 
-				} );
+						render();
+
+					} );
+
+				};
+
+				loadPointCloud( 'binary/Zaghetto.pcd' );
 
 				window.addEventListener( 'resize', onWindowResize );
 

粤ICP备19079148号