Sfoglia il codice sorgente

Fixed bug in isGltf1(); added safety checks when parsing for glTF attributes

Alan Millman 7 anni fa
parent
commit
1fc2c44ac3

+ 7 - 1
editor/js/Loader.js

@@ -588,6 +588,7 @@ var Loader = function ( editor ) {
 
 		if ( typeof contents === 'string' ) {
 
+			// contents is a JSON string
 			resultContent = contents;
 
 		} else {
@@ -596,10 +597,15 @@ var Loader = function ( editor ) {
 
 			if ( magic === 'glTF' ) {
 
-				return false;
+				// contents is a .glb file; extract the version
+				var u32bytes = new Uint8Array( contents, 4, 4 );
+				var versionNumber = new Uint32Array(u32bytes)[0];
+
+				return ( versionNumber < 2 );
 
 			} else {
 
+				// contents is a .gltf file
 				resultContent = THREE.LoaderUtils.decodeText( new Uint8Array( contents ) );
 
 			}

+ 622 - 0
editor/js/Loader.js~RF6842b54.TMP

@@ -0,0 +1,622 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+var Loader = function ( editor ) {
+
+	var scope = this;
+	var signals = editor.signals;
+
+	this.texturePath = '';
+
+	this.loadFile = function ( file ) {
+
+		var filename = file.name;
+		var extension = filename.split( '.' ).pop().toLowerCase();
+
+		var reader = new FileReader();
+		reader.addEventListener( 'progress', function ( event ) {
+
+			var size = '(' + Math.floor( event.total / 1000 ).format() + ' KB)';
+			var progress = Math.floor( ( event.loaded / event.total ) * 100 ) + '%';
+			console.log( 'Loading', filename, size, progress );
+
+		} );
+
+		switch ( extension ) {
+
+			case '3ds':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var loader = new THREE.TDSLoader();
+					var object = loader.parse( event.target.result );
+
+					editor.execute( new AddObjectCommand( object ) );
+
+				}, false );
+				reader.readAsArrayBuffer( file );
+
+				break;
+
+			case 'amf':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var loader = new THREE.AMFLoader();
+					var amfobject = loader.parse( event.target.result );
+
+					editor.execute( new AddObjectCommand( amfobject ) );
+
+				}, false );
+				reader.readAsArrayBuffer( file );
+
+				break;
+
+			case 'awd':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var loader = new THREE.AWDLoader();
+					var scene = loader.parse( event.target.result );
+
+					editor.execute( new SetSceneCommand( scene ) );
+
+				}, false );
+				reader.readAsArrayBuffer( file );
+
+				break;
+
+			case 'babylon':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+					var json = JSON.parse( contents );
+
+					var loader = new THREE.BabylonLoader();
+					var scene = loader.parse( json );
+
+					editor.execute( new SetSceneCommand( scene ) );
+
+				}, false );
+				reader.readAsText( file );
+
+				break;
+
+			case 'babylonmeshdata':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+					var json = JSON.parse( contents );
+
+					var loader = new THREE.BabylonLoader();
+
+					var geometry = loader.parseGeometry( json );
+					var material = new THREE.MeshStandardMaterial();
+
+					var mesh = new THREE.Mesh( geometry, material );
+					mesh.name = filename;
+
+					editor.execute( new AddObjectCommand( mesh ) );
+
+				}, false );
+				reader.readAsText( file );
+
+				break;
+
+			case 'ctm':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var data = new Uint8Array( event.target.result );
+
+					var stream = new CTM.Stream( data );
+					stream.offset = 0;
+
+					var loader = new THREE.CTMLoader();
+					loader.createModel( new CTM.File( stream ), function( geometry ) {
+
+						geometry.sourceType = "ctm";
+						geometry.sourceFile = file.name;
+
+						var material = new THREE.MeshStandardMaterial();
+
+						var mesh = new THREE.Mesh( geometry, material );
+						mesh.name = filename;
+
+						editor.execute( new AddObjectCommand( mesh ) );
+
+					} );
+
+				}, false );
+				reader.readAsArrayBuffer( file );
+
+				break;
+
+			case 'dae':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var loader = new THREE.ColladaLoader();
+					var collada = loader.parse( contents );
+
+					collada.scene.name = filename;
+
+					editor.execute( new AddObjectCommand( collada.scene ) );
+
+				}, false );
+				reader.readAsText( file );
+
+				break;
+
+			case 'fbx':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var loader = new THREE.FBXLoader();
+					var object = loader.parse( contents );
+
+					editor.execute( new AddObjectCommand( object ) );
+
+				}, false );
+				reader.readAsArrayBuffer( file );
+
+				break;
+
+			case 'glb':
+			case 'gltf':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+					var loader;
+
+					if ( isGltf1( contents ) ) {
+
+						loader = new THREE.LegacyGLTFLoader();
+
+					} else {
+
+						loader = new THREE.GLTFLoader();
+
+					}
+
+					loader.parse( contents, '', function ( result ) {
+
+						result.scene.name = filename;
+						editor.execute( new AddObjectCommand( result.scene ) );
+
+					} );
+
+				}, false );
+				reader.readAsArrayBuffer( file );
+
+				break;
+
+			case 'js':
+			case 'json':
+
+			case '3geo':
+			case '3mat':
+			case '3obj':
+			case '3scn':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					// 2.0
+
+					if ( contents.indexOf( 'postMessage' ) !== - 1 ) {
+
+						var blob = new Blob( [ contents ], { type: 'text/javascript' } );
+						var url = URL.createObjectURL( blob );
+
+						var worker = new Worker( url );
+
+						worker.onmessage = function ( event ) {
+
+							event.data.metadata = { version: 2 };
+							handleJSON( event.data, file, filename );
+
+						};
+
+						worker.postMessage( Date.now() );
+
+						return;
+
+					}
+
+					// >= 3.0
+
+					var data;
+
+					try {
+
+						data = JSON.parse( contents );
+
+					} catch ( error ) {
+
+						alert( error );
+						return;
+
+					}
+
+					handleJSON( data, file, filename );
+
+				}, false );
+				reader.readAsText( file );
+
+				break;
+
+
+			case 'kmz':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var loader = new THREE.KMZLoader();
+					var collada = loader.parse( event.target.result );
+
+					collada.scene.name = filename;
+
+					editor.execute( new AddObjectCommand( collada.scene ) );
+
+				}, false );
+				reader.readAsArrayBuffer( file );
+
+				break;
+
+			case 'md2':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var geometry = new THREE.MD2Loader().parse( contents );
+					var material = new THREE.MeshStandardMaterial( {
+						morphTargets: true,
+						morphNormals: true
+					} );
+
+					var mesh = new THREE.Mesh( geometry, material );
+					mesh.mixer = new THREE.AnimationMixer( mesh );
+					mesh.name = filename;
+
+					editor.execute( new AddObjectCommand( mesh ) );
+
+				}, false );
+				reader.readAsArrayBuffer( file );
+
+				break;
+
+			case 'obj':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var object = new THREE.OBJLoader().parse( contents );
+					object.name = filename;
+
+					editor.execute( new AddObjectCommand( object ) );
+
+				}, false );
+				reader.readAsText( file );
+
+				break;
+
+			case 'playcanvas':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+					var json = JSON.parse( contents );
+
+					var loader = new THREE.PlayCanvasLoader();
+					var object = loader.parse( json );
+
+					editor.execute( new AddObjectCommand( object ) );
+
+				}, false );
+				reader.readAsText( file );
+
+				break;
+
+			case 'ply':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var geometry = new THREE.PLYLoader().parse( contents );
+					geometry.sourceType = "ply";
+					geometry.sourceFile = file.name;
+
+					var material = new THREE.MeshStandardMaterial();
+
+					var mesh = new THREE.Mesh( geometry, material );
+					mesh.name = filename;
+
+					editor.execute( new AddObjectCommand( mesh ) );
+
+				}, false );
+				reader.readAsArrayBuffer( file );
+
+				break;
+
+			case 'stl':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var geometry = new THREE.STLLoader().parse( contents );
+					geometry.sourceType = "stl";
+					geometry.sourceFile = file.name;
+
+					var material = new THREE.MeshStandardMaterial();
+
+					var mesh = new THREE.Mesh( geometry, material );
+					mesh.name = filename;
+
+					editor.execute( new AddObjectCommand( mesh ) );
+
+				}, false );
+
+				if ( reader.readAsBinaryString !== undefined ) {
+
+					reader.readAsBinaryString( file );
+
+				} else {
+
+					reader.readAsArrayBuffer( file );
+
+				}
+
+				break;
+
+			/*
+			case 'utf8':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var geometry = new THREE.UTF8Loader().parse( contents );
+					var material = new THREE.MeshLambertMaterial();
+
+					var mesh = new THREE.Mesh( geometry, material );
+
+					editor.execute( new AddObjectCommand( mesh ) );
+
+				}, false );
+				reader.readAsBinaryString( file );
+
+				break;
+			*/
+
+			case 'vtk':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var geometry = new THREE.VTKLoader().parse( contents );
+					geometry.sourceType = "vtk";
+					geometry.sourceFile = file.name;
+
+					var material = new THREE.MeshStandardMaterial();
+
+					var mesh = new THREE.Mesh( geometry, material );
+					mesh.name = filename;
+
+					editor.execute( new AddObjectCommand( mesh ) );
+
+				}, false );
+				reader.readAsText( file );
+
+				break;
+
+			case 'wrl':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var result = new THREE.VRMLLoader().parse( contents );
+
+					editor.execute( new SetSceneCommand( result ) );
+
+				}, false );
+				reader.readAsText( file );
+
+				break;
+
+			case 'zip':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var zip = new JSZip( contents );
+
+					// BLOCKS
+
+					if ( zip.files[ 'model.obj' ] && zip.files[ 'materials.mtl' ] ) {
+
+						var materials = new THREE.MTLLoader().parse( zip.file( 'materials.mtl' ).asText() );
+						var object = new THREE.OBJLoader().setMaterials( materials ).parse( zip.file( 'model.obj' ).asText() );
+						editor.execute( new AddObjectCommand( object ) );
+
+					}
+
+				}, false );
+				reader.readAsBinaryString( file );
+
+				break;
+
+			default:
+
+				alert( 'Unsupported file format (' + extension +  ').' );
+
+				break;
+
+		}
+
+	};
+
+	function handleJSON( data, file, filename ) {
+
+		if ( data.metadata === undefined ) { // 2.0
+
+			data.metadata = { type: 'Geometry' };
+
+		}
+
+		if ( data.metadata.type === undefined ) { // 3.0
+
+			data.metadata.type = 'Geometry';
+
+		}
+
+		if ( data.metadata.formatVersion !== undefined ) {
+
+			data.metadata.version = data.metadata.formatVersion;
+
+		}
+
+		switch ( data.metadata.type.toLowerCase() ) {
+
+			case 'buffergeometry':
+
+				var loader = new THREE.BufferGeometryLoader();
+				var result = loader.parse( data );
+
+				var mesh = new THREE.Mesh( result );
+
+				editor.execute( new AddObjectCommand( mesh ) );
+
+				break;
+
+			case 'geometry':
+
+				var loader = new THREE.JSONLoader();
+				loader.setTexturePath( scope.texturePath );
+
+				var result = loader.parse( data );
+
+				var geometry = result.geometry;
+				var material;
+
+				if ( result.materials !== undefined ) {
+
+					if ( result.materials.length > 1 ) {
+
+						material = new THREE.MultiMaterial( result.materials );
+
+					} else {
+
+						material = result.materials[ 0 ];
+
+					}
+
+				} else {
+
+					material = new THREE.MeshStandardMaterial();
+
+				}
+
+				geometry.sourceType = "ascii";
+				geometry.sourceFile = file.name;
+
+				var mesh;
+
+				if ( geometry.animation && geometry.animation.hierarchy ) {
+
+					mesh = new THREE.SkinnedMesh( geometry, material );
+
+				} else {
+
+					mesh = new THREE.Mesh( geometry, material );
+
+				}
+
+				mesh.name = filename;
+
+				editor.execute( new AddObjectCommand( mesh ) );
+
+				break;
+
+			case 'object':
+
+				var loader = new THREE.ObjectLoader();
+				loader.setTexturePath( scope.texturePath );
+
+				var result = loader.parse( data );
+
+				if ( result instanceof THREE.Scene ) {
+
+					editor.execute( new SetSceneCommand( result ) );
+
+				} else {
+
+					editor.execute( new AddObjectCommand( result ) );
+
+				}
+
+				break;
+
+			case 'app':
+
+				editor.fromJSON( data );
+
+				break;
+
+		}
+
+	}
+
+	function isGltf1( contents ) {
+
+		var contentType = typeof contents;
+		var resultContent;
+
+		if( contentType !== 'string' ) {
+
+			var magic = THREE.LoaderUtils.decodeText( new Uint8Array( contents, 0, 4 ) );
+
+			if ( magic === 'glTF' ) {
+
+				// contents is a .glb file; extract the version
+				var u32bytes = new Uint8Array( contents, 4, 4 );
+				var versionNumber = new Uint32Array(u32bytes)[0];
+
+				return ( versionNumber < 2 );
+
+			} else {
+
+				// contents is a .gltf file
+				resultContent = THREE.LoaderUtils.decodeText( new Uint8Array( contents ) );
+
+			}
+
+		} else {
+
+			// contents is a JSON string
+			resultContent = contents;
+
+		}
+
+		var json = JSON.parse( resultContent );
+
+		return ( json.asset != undefined && json.asset.version[ 0 ] < 2 );
+
+	}
+
+};

+ 16 - 6
examples/js/loaders/deprecated/LegacyGLTFLoader.js

@@ -1635,14 +1635,24 @@ THREE.LegacyGLTFLoader = ( function () {
 									break;
 
 								default:
-									var material = json.materials[ primitive.material ];
-									var parameters = json.techniques[ material.technique ].parameters;
-									
-									for( var attributeName in parameters ) {
 
-										if( parameters[attributeName]['semantic'] === attributeId ) {
+									if ( primitive.material ) {
 
-											geometry.addAttribute( attributeName, bufferAttribute );
+										var material = json.materials[ primitive.material ];
+
+										if ( material.technique ) {
+
+											var parameters = json.techniques[ material.technique ].parameters;
+
+											for( var attributeName in parameters ) {
+
+												if ( parameters [ attributeName ][ 'semantic' ] === attributeId ) {
+
+													geometry.addAttribute( attributeName, bufferAttribute );
+
+												}
+
+											}
 
 										}