瀏覽代碼

mprove performance by only mapping between element properties and (#25210)

geometry properties as required and avoid converting entire binary files
to ascii for header parsing.

Co-authored-by: aardgoose <[email protected]>
aardgoose 2 年之前
父節點
當前提交
534003a4ef
共有 1 個文件被更改,包括 106 次插入45 次删除
  1. 106 45
      examples/jsm/loaders/PLYLoader.js

+ 106 - 45
examples/jsm/loaders/PLYLoader.js

@@ -298,6 +298,40 @@ class PLYLoader extends Loader {
 
 
 		}
 		}
 
 
+		function mapElementAttributes( properties ) {
+
+			const elementNames = properties.map(  property => { return property.name } );
+
+			function findAttrName( names ) {
+
+				for ( let i = 0, l = names.length; i < l; i ++ ) {
+
+					const name = names[ i ];
+
+					if ( name in elementNames ) return name;
+
+				}
+
+				return null;
+
+			}
+
+			return {
+				attrX: findAttrName( [ 'x', 'px', 'posx' ] ) || 'x',
+				attrY: findAttrName( [ 'y', 'py', 'posy' ] ) || 'y',
+				attrZ: findAttrName( [ 'z', 'pz', 'posz' ] ) || 'z',
+				attrNX: findAttrName( [ 'nx', 'normalx' ] ),
+				attrNY: findAttrName( [ 'ny', 'normaly' ] ),
+				attrNZ: findAttrName( [ 'nz', 'normalz' ] ),
+				attrS: findAttrName( [ 's', 'u', 'texture_u', 'tx' ] ),
+				attrT: findAttrName( [ 't', 'v', 'texture_v', 'ty' ] ),
+				attrR: findAttrName( [ 'red', 'diffuse_red', 'r', 'diffuse_r' ] ),
+				attrG: findAttrName( [ 'green', 'diffuse_green', 'g', 'diffuse_g' ] ),
+				attrB: findAttrName( [ 'blue', 'diffuse_blue', 'b', 'diffuse_b' ] ),
+			};
+
+		}
+
 		function parseASCII( data, header ) {
 		function parseASCII( data, header ) {
 
 
 			// PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)
 			// PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)
@@ -317,6 +351,8 @@ class PLYLoader extends Loader {
 			const lines = body.split( /\r\n|\r|\n/ );
 			const lines = body.split( /\r\n|\r|\n/ );
 			let currentElement = 0;
 			let currentElement = 0;
 			let currentElementCount = 0;
 			let currentElementCount = 0;
+			let elementDesc = header.elements[ currentElement ];
+			let attributeMap = mapElementAttributes( elementDesc.properties );
 
 
 			for ( let i = 0; i < lines.length; i ++ ) {
 			for ( let i = 0; i < lines.length; i ++ ) {
 
 
@@ -328,16 +364,19 @@ class PLYLoader extends Loader {
 
 
 				}
 				}
 
 
-				if ( currentElementCount >= header.elements[ currentElement ].count ) {
+				if ( currentElementCount >= elementDesc.count ) {
 
 
 					currentElement ++;
 					currentElement ++;
 					currentElementCount = 0;
 					currentElementCount = 0;
+					elementDesc = header.elements[ currentElement ];
+
+					attributeMap = mapElementAttributes( elementDesc.properties );
 
 
 				}
 				}
 
 
-				const element = parseASCIIElement( header.elements[ currentElement ].properties, line );
+				const element = parseASCIIElement( elementDesc.properties, line );
 
 
-				handleElement( buffer, header.elements[ currentElement ].name, element );
+				handleElement( buffer, elementDesc.name, element, attributeMap );
 
 
 				currentElementCount ++;
 				currentElementCount ++;
 
 
@@ -412,56 +451,30 @@ class PLYLoader extends Loader {
 
 
 		}
 		}
 
 
-		function handleElement( buffer, elementName, element ) {
-
-			function findAttrName( names ) {
-
-				for ( let i = 0, l = names.length; i < l; i ++ ) {
-
-					const name = names[ i ];
-
-					if ( name in element ) return name;
-
-				}
-
-				return null;
-
-			}
-
-			const attrX = findAttrName( [ 'x', 'px', 'posx' ] ) || 'x';
-			const attrY = findAttrName( [ 'y', 'py', 'posy' ] ) || 'y';
-			const attrZ = findAttrName( [ 'z', 'pz', 'posz' ] ) || 'z';
-			const attrNX = findAttrName( [ 'nx', 'normalx' ] );
-			const attrNY = findAttrName( [ 'ny', 'normaly' ] );
-			const attrNZ = findAttrName( [ 'nz', 'normalz' ] );
-			const attrS = findAttrName( [ 's', 'u', 'texture_u', 'tx' ] );
-			const attrT = findAttrName( [ 't', 'v', 'texture_v', 'ty' ] );
-			const attrR = findAttrName( [ 'red', 'diffuse_red', 'r', 'diffuse_r' ] );
-			const attrG = findAttrName( [ 'green', 'diffuse_green', 'g', 'diffuse_g' ] );
-			const attrB = findAttrName( [ 'blue', 'diffuse_blue', 'b', 'diffuse_b' ] );
+		function handleElement( buffer, elementName, element, cacheEntry ) {
 
 
 			if ( elementName === 'vertex' ) {
 			if ( elementName === 'vertex' ) {
 
 
-				buffer.vertices.push( element[ attrX ], element[ attrY ], element[ attrZ ] );
+				buffer.vertices.push( element[ cacheEntry.attrX ], element[ cacheEntry.attrY ], element[ cacheEntry.attrZ ] );
 
 
-				if ( attrNX !== null && attrNY !== null && attrNZ !== null ) {
+				if ( cacheEntry.attrNX !== null && cacheEntry.attrNY !== null && cacheEntry.attrNZ !== null ) {
 
 
-					buffer.normals.push( element[ attrNX ], element[ attrNY ], element[ attrNZ ] );
+					buffer.normals.push( element[ cacheEntry.attrNX ], element[ cacheEntry.attrNY ], element[ cacheEntry.attrNZ ] );
 
 
 				}
 				}
 
 
-				if ( attrS !== null && attrT !== null ) {
+				if ( cacheEntry.attrS !== null && cacheEntry.attrT !== null ) {
 
 
-					buffer.uvs.push( element[ attrS ], element[ attrT ] );
+					buffer.uvs.push( element[ cacheEntry.attrS ], element[ cacheEntry.attrT ] );
 
 
 				}
 				}
 
 
-				if ( attrR !== null && attrG !== null && attrB !== null ) {
+				if ( cacheEntry.attrR !== null && cacheEntry.attrG !== null && cacheEntry.attrB !== null ) {
 
 
 					_color.setRGB(
 					_color.setRGB(
-						element[ attrR ] / 255.0,
-						element[ attrG ] / 255.0,
-						element[ attrB ] / 255.0
+						element[ cacheEntry.attrR ] / 255.0,
+						element[ cacheEntry.attrG ] / 255.0,
+						element[ cacheEntry.attrB ] / 255.0
 					).convertSRGBToLinear();
 					).convertSRGBToLinear();
 
 
 					buffer.colors.push( _color.r, _color.g, _color.b );
 					buffer.colors.push( _color.r, _color.g, _color.b );
@@ -573,13 +586,16 @@ class PLYLoader extends Loader {
 
 
 			for ( let currentElement = 0; currentElement < header.elements.length; currentElement ++ ) {
 			for ( let currentElement = 0; currentElement < header.elements.length; currentElement ++ ) {
 
 
-				for ( let currentElementCount = 0; currentElementCount < header.elements[ currentElement ].count; currentElementCount ++ ) {
+				const elementDesc = header.elements[ currentElement ];
+				const attributeMap = mapElementAttributes( elementDesc.properties );
 
 
-					result = binaryReadElement( body, loc, header.elements[ currentElement ].properties, little_endian );
+				for ( let currentElementCount = 0; currentElementCount < elementDesc.count; currentElementCount ++ ) {
+
+					result = binaryReadElement( body, loc, elementDesc.properties, little_endian );
 					loc += result[ 1 ];
 					loc += result[ 1 ];
 					const element = result[ 0 ];
 					const element = result[ 0 ];
 
 
-					handleElement( buffer, header.elements[ currentElement ].name, element );
+					handleElement( buffer, elementDesc.name, element, attributeMap );
 
 
 				}
 				}
 
 
@@ -589,6 +605,40 @@ class PLYLoader extends Loader {
 
 
 		}
 		}
 
 
+		function extractHeaderText( bytes ) {
+
+			let i = 0;
+			let cont = true;
+
+			let line = '';
+			const lines = [];
+
+			do {
+
+				const c = String.fromCharCode( bytes[ i++ ] );
+
+				if ( c !== "\n" && c !== "\r" ) {
+
+					line += c;
+
+				} else {
+
+					if ( line === 'end_header' ) cont = false;
+					if ( line !== '' ) {
+
+						lines.push( line );
+						line = '';
+
+					}
+
+				}
+
+			}  while ( cont && i < bytes.length );
+
+			return lines.join( "\r" ) + "\r";
+
+		}
+
 		//
 		//
 
 
 		let geometry;
 		let geometry;
@@ -596,10 +646,21 @@ class PLYLoader extends Loader {
 
 
 		if ( data instanceof ArrayBuffer ) {
 		if ( data instanceof ArrayBuffer ) {
 
 
-			const text = LoaderUtils.decodeText( new Uint8Array( data ) );
-			const header = parseHeader( text );
+			const bytes = new Uint8Array( data );
+			const headerText = extractHeaderText( bytes );
+			const header = parseHeader( headerText );
+
+			if ( header.format === 'ascii' ) {
+
+				const text = LoaderUtils.decodeText( bytes );
+
+				geometry = parseASCII( text, header );
 
 
-			geometry = header.format === 'ascii' ? parseASCII( text, header ) : parseBinary( data, header );
+			} else {
+
+				geometry = parseBinary( data, header );
+
+			}
 
 
 		} else {
 		} else {