فهرست منبع

Merge pull request #11919 from Mugen87/assimp

AssimpJSONLoader: Refactoring
Mr.doob 8 سال پیش
والد
کامیت
47b84060aa
3فایلهای تغییر یافته به همراه168 افزوده شده و 232 حذف شده
  1. 124 178
      examples/js/loaders/AssimpJSONLoader.js
  2. 9 9
      examples/models/assimp/interior/interior.assimp.json
  3. 35 45
      examples/webgl_loader_assimp2json.html

+ 124 - 178
examples/js/loaders/AssimpJSONLoader.js

@@ -27,38 +27,38 @@ THREE.AssimpJSONLoader.prototype = {
 
 		var scope = this;
 
-		this.texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : this.extractUrlBase( url );
+		var path = THREE.Loader.prototype.extractUrlBase( url );
 
 		var loader = new THREE.FileLoader( this.manager );
 		loader.load( url, function ( text ) {
 
-			var json = JSON.parse( text ), scene, metadata;
+			var json = JSON.parse( text );
+			var metadata = json.__metadata__;
+
+			// check if __metadata__ meta header is present
+			// this header is used to disambiguate between different JSON-based file formats
 
-			// Check __metadata__ meta header if present
-			// This header is used to disambiguate between
-			// different JSON-based file formats.
-			metadata = json.__metadata__;
 			if ( typeof metadata !== 'undefined' ) {
 
-				// Check if assimp2json at all
+				// check if assimp2json at all
+
 				if ( metadata.format !== 'assimp2json' ) {
 
-					onError( 'Not an assimp2json scene' );
+					onError( 'THREE.AssimpJSONLoader: Not an assimp2json scene.' );
 					return;
 
-				}
-				// Check major format version
-				else if ( metadata.version < 100 && metadata.version >= 200 ) {
+				// check major format version
+
+				} else if ( metadata.version < 100 && metadata.version >= 200 ) {
 
-					onError( 'Unsupported assimp2json file format version' );
+					onError( 'THREE.AssimpJSONLoader: Unsupported assimp2json file format version.' );
 					return;
 
 				}
 
 			}
 
-			scene = scope.parse( json );
-			onLoad( scene );
+			onLoad( scope.parse( json, path ) );
 
 		}, onProgress, onError );
 
@@ -70,249 +70,195 @@ THREE.AssimpJSONLoader.prototype = {
 
 	},
 
-	setTexturePath: function ( value ) {
+	parse: function ( json, path ) {
 
-		this.texturePath = value;
+		function parseList( json, handler ) {
 
-	},
-
-	extractUrlBase: function ( url ) {
+			var meshes = new Array( json.length );
 
-		// from three/src/loaders/Loader.js
-		var parts = url.split( '/' );
-		parts.pop();
-		return ( parts.length < 1 ? '.' : parts.join( '/' ) ) + '/';
-
-	},
+			for ( var i = 0; i < json.length; ++ i ) {
 
-	parse: function ( json ) {
+				meshes[ i ] = handler.call( this, json[ i ] );
 
-		var meshes = this.parseList ( json.meshes, this.parseMesh );
-		var materials = this.parseList ( json.materials, this.parseMaterial );
-		return this.parseObject( json, json.rootnode, meshes, materials );
-
-	},
-
-	parseList : function( json, handler ) {
-
-		var meshes = new Array( json.length );
-		for ( var i = 0; i < json.length; ++ i ) {
+			}
 
-			meshes[ i ] = handler.call( this, json[ i ] );
+			return meshes;
 
 		}
-		return meshes;
-
-	},
 
-	parseMesh : function( json ) {
+		function parseMesh( json ) {
 
-		var geometry = new THREE.BufferGeometry();
+			var geometry = new THREE.BufferGeometry();
 
-		var i, l, face;
+			var i, l, face;
 
-		var indices = [];
+			var indices = [];
 
-		var vertices = json.vertices || [];
-		var normals = json.normals || [];
-		var uvs = json.texturecoords || [];
-		var colors = json.colors || [];
+			var vertices = json.vertices || [];
+			var normals = json.normals || [];
+			var uvs = json.texturecoords || [];
+			var colors = json.colors || [];
 
-		uvs = uvs[ 0 ] || []; // only support for a single set of uvs
+			uvs = uvs[ 0 ] || []; // only support for a single set of uvs
 
-		for ( i = 0, l = json.faces.length; i < l; i ++ ) {
+			for ( i = 0, l = json.faces.length; i < l; i ++ ) {
 
-			face = json.faces[ i ];
-			indices.push( face[ 0 ], face[ 1 ], face[ 2 ] );
+				face = json.faces[ i ];
+				indices.push( face[ 0 ], face[ 1 ], face[ 2 ] );
 
-		}
-
-		geometry.setIndex( indices );
-		geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
-
-		if ( normals.length > 0 ) {
-
-			geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
-
-		}
-
-		if ( uvs.length > 0 ) {
-
-			geometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
+			}
 
-		}
+			geometry.setIndex( indices );
+			geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
 
-		if ( colors.length > 0 ) {
+			if ( normals.length > 0 ) {
 
-			geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
+				geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
 
-		}
+			}
 
-		geometry.computeBoundingSphere();
+			if ( uvs.length > 0 ) {
 
-		return geometry;
+				geometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
 
-	},
+			}
 
-	parseMaterial : function( json ) {
+			if ( colors.length > 0 ) {
 
-		var mat = null;
-		var scope = this;
-		var i, prop, has_textures = [],
+				geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
 
-		init_props = {};
+			}
 
-		function toColor( value_arr ) {
+			geometry.computeBoundingSphere();
 
-			var col = new THREE.Color();
-			col.setRGB( value_arr[ 0 ], value_arr[ 1 ], value_arr[ 2 ] );
-			return col;
+			return geometry;
 
 		}
 
-		function defaultTexture() {
+		function parseMaterial( json ) {
 
-			var im = new Image();
-			im.width = 1;
-			im.height = 1;
-			return new THREE.Texture( im );
+			var material = new THREE.MeshPhongMaterial();
 
-		}
+			for ( var i in json.properties ) {
 
-		for ( i in json.properties ) {
+				var property = json.properties[ i ];
+				var key = property.key;
+				var value = property.value;
 
-			prop = json.properties[ i ];
+				switch ( key ) {
 
-			if ( prop.key === '$tex.file' ) {
+					case '$tex.file': {
 
-				// prop.semantic gives the type of the texture
-				// 1: diffuse
-				// 2: specular mao
-				// 5: height map (bumps)
-				// 6: normal map
-				// more values (i.e. emissive, environment) are known by assimp and may be relevant
-				if ( prop.semantic === 1 || prop.semantic === 5 || prop.semantic === 6 || prop.semantic === 2 ) {
+						var semantic =  property.semantic;
 
-					( function( semantic ) {
+						// prop.semantic gives the type of the texture
+						// 1: diffuse
+						// 2: specular mao
+						// 5: height map (bumps)
+						// 6: normal map
+						// more values (i.e. emissive, environment) are known by assimp and may be relevant
 
-						var loader = new THREE.TextureLoader( scope.manager ),
-						keyname;
+						if ( semantic === 1 || semantic === 2 || semantic === 5 || semantic === 6 ) {
 
-						if ( semantic === 1 ) {
+							var keyname;
 
-							keyname = 'map';
+							switch ( semantic ) {
 
-						} else if ( semantic === 5 ) {
+								case 1:
+									keyname = 'map';
+									break;
+								case 2:
+									keyname = 'specularMap';
+									break;
+								case 5:
+									keyname = 'bumpMap';
+									break;
+								case 6:
+									keyname = 'normalMap';
+									break;
 
-							keyname = 'bumpMap';
+							}
 
-						} else if ( semantic === 6 ) {
+							var texture = textureLoader.load( value );
 
-							keyname = 'normalMap';
+							// TODO: read texture settings from assimp.
+							// Wrapping is the default, though.
 
-						} else if ( semantic === 2 ) {
+							texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
 
-							keyname = 'specularMap';
+							material[ keyname ] = texture;
 
 						}
 
-						has_textures.push( keyname );
+						break;
 
-						loader.setCrossOrigin( this.crossOrigin );
-						var material_url = scope.texturePath + '/' + prop.value;
-						material_url = material_url.replace( /\\/g, '/' );
-						loader.load( material_url, function( tex ) {
+					}
 
-							if ( tex ) {
+					case '?mat.name':
+						material.name = value;
+						break;
 
-								// TODO: read texture settings from assimp.
-								// Wrapping is the default, though.
-								tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
+					case '$clr.diffuse':
+						material.color.fromArray( value );
+						break;
 
-								mat[ keyname ] = tex;
-								mat.needsUpdate = true;
+					case '$clr.specular':
+						material.specular.fromArray( value );
+						break;
 
-							}
+					case '$clr.emissive':
+						material.emissive.fromArray( value );
+						break;
 
-						} );
+					case '$mat.shininess':
+						material.shininess = value;
+						break;
 
-					} )( prop.semantic );
+					case '$mat.shadingm':
+						// aiShadingMode_Flat
+						material.flatShading = ( value === 1 ) ? true : false;
+						break;
 
 				}
 
-			} else if ( prop.key === '?mat.name' ) {
-
-				init_props.name = prop.value;
-
-			} else if ( prop.key === '$clr.diffuse' ) {
-
-				init_props.color = toColor( prop.value );
-
-			} else if ( prop.key === '$clr.specular' ) {
-
-				init_props.specular = toColor( prop.value );
+			}
 
-			} else if ( prop.key === '$clr.emissive' ) {
+			return material;
 
-				init_props.emissive = toColor( prop.value );
+		}
 
-			} else if ( prop.key === '$mat.shadingm' ) {
+		function parseObject( json, node, meshes, materials ) {
 
-				// aiShadingMode_Flat
-				if ( prop.value === 1 ) {
+			var obj = new THREE.Object3D(),	i, idx;
 
-					init_props.flatShading = true;
+			obj.name = node.name || '';
+			obj.matrix = new THREE.Matrix4().fromArray( node.transformation ).transpose();
+			obj.matrix.decompose( obj.position, obj.quaternion, obj.scale );
 
-				}
+			for ( i = 0; node.meshes && i < node.meshes.length; i ++ ) {
 
-			} else if ( prop.key === '$mat.shininess' ) {
-
-				init_props.shininess = prop.value;
+				idx = node.meshes[ i ];
+				obj.add( new THREE.Mesh( meshes[ idx ], materials[ json.meshes[ idx ].materialindex ] ) );
 
 			}
 
-		}
-
-		// note: three.js does not like it when a texture is added after the geometry
-		// has been rendered once, see http://stackoverflow.com/questions/16531759/.
-		// for this reason we fill all slots upfront with default textures
-		if ( has_textures.length ) {
+			for ( i = 0; node.children && i < node.children.length; i ++ ) {
 
-			for ( i = has_textures.length - 1; i >= 0; -- i ) {
-
-				init_props[ has_textures[ i ]] = defaultTexture();
+				obj.add( parseObject( json, node.children[ i ], meshes, materials ) );
 
 			}
 
-		}
-
-		mat = new THREE.MeshPhongMaterial( init_props );
-		return mat;
-
-	},
-
-	parseObject : function( json, node, meshes, materials ) {
-
-		var obj = new THREE.Object3D(),	i, idx;
-
-		obj.name = node.name || "";
-		obj.matrix = new THREE.Matrix4().fromArray( node.transformation ).transpose();
-		obj.matrix.decompose( obj.position, obj.quaternion, obj.scale );
-
-		for ( i = 0; node.meshes && i < node.meshes.length; ++ i ) {
-
-			idx = node.meshes[ i ];
-			obj.add( new THREE.Mesh( meshes[ idx ], materials[ json.meshes[ idx ].materialindex ] ) );
+			return obj;
 
 		}
 
-		for ( i = 0; node.children && i < node.children.length; ++ i ) {
+		var textureLoader = new THREE.TextureLoader( this.manager );
+		textureLoader.setPath( path ).setCrossOrigin( this.crossOrigin );
 
-			obj.add( this.parseObject( json, node.children[ i ], meshes, materials ) );
-
-		}
-
-		return obj;
+		var meshes = parseList ( json.meshes, parseMesh );
+		var materials = parseList ( json.materials, parseMaterial );
+		return parseObject( json, json.rootnode, meshes, materials );
 
 	}
+
 };

+ 9 - 9
examples/models/assimp/interior/interior.assimp.json

@@ -2373,9 +2373,9 @@
 					,"index": 0
 					,"type": 1
 					,"value": [
-						 0.898039
-						,0.898039
-						,0.898039
+						 0.1
+						,0.1
+						,0.1
 					]
 				}
 				,{
@@ -2490,9 +2490,9 @@
 					,"index": 0
 					,"type": 1
 					,"value": [
-						 0.898039
-						,0.898039
-						,0.898039
+						 0.1
+						,0.1
+						,0.1
 					]
 				}
 				,{
@@ -2607,9 +2607,9 @@
 					,"index": 0
 					,"type": 1
 					,"value": [
-						 0.898039
-						,0.898039
-						,0.898039
+						 0.1
+						,0.1
+						,0.1
 					]
 				}
 				,{

+ 35 - 45
examples/webgl_loader_assimp2json.html

@@ -68,84 +68,75 @@
 
 			*/
 
-			var container, stats;
-			var camera, scene, renderer, objects;
-			var clock = new THREE.Clock();
+			var container, stats, clock;
+			var camera, scene, renderer;
 
-			// init scene
 			init();
+			animate();
 
-			var onProgress = function ( xhr ) {
-				if ( xhr.lengthComputable ) {
-					var percentComplete = xhr.loaded / xhr.total * 100;
-					console.log( Math.round(percentComplete, 2) + '% downloaded' );
-				}
-			};
+			//
 
-			var onError = function ( xhr ) {
-			};
+			function init() {
 
-			// Load jeep model using the AssimpJSONLoader
-			var loader1 = new THREE.AssimpJSONLoader();
-			loader1.load( 'models/assimp/jeep/jeep.assimp.json', function ( object ) {
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
 
-				object.scale.multiplyScalar( 0.2 );
-				scene.add( object );
+				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 2000 );
 
-			}, onProgress, onError );
+				scene = new THREE.Scene();
 
-			// load interior model
-			var loader2 = new THREE.AssimpJSONLoader();
-			loader2.load( 'models/assimp/interior/interior.assimp.json', function ( object ) {
+				clock = new THREE.Clock();
 
-				scene.add( object );
+				// load jeep model
 
-			}, onProgress, onError );
+				var loader1 = new THREE.AssimpJSONLoader();
+				loader1.load( 'models/assimp/jeep/jeep.assimp.json', function ( object ) {
 
-			animate();
+					object.scale.multiplyScalar( 0.2 );
+					scene.add( object );
 
+				} );
 
-			//
+				// load interior model
 
-			function init() {
+				var loader2 = new THREE.AssimpJSONLoader();
+				loader2.load( 'models/assimp/interior/interior.assimp.json', function ( object ) {
 
-				container = document.createElement( 'div' );
-				document.body.appendChild( container );
+					scene.add( object );
 
-				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 2000 );
-				camera.position.set( 2, 4, 5 );
+				} );
 
-				scene = new THREE.Scene();
-				scene.fog = new THREE.FogExp2( 0x000000, 0.035 );
+				//
 
-				// Lights
-				scene.add( new THREE.AmbientLight( 0xcccccc ) );
+				var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
+				scene.add( ambientLight );
 
 				var directionalLight = new THREE.DirectionalLight( 0xeeeeee );
-				directionalLight.position.x = Math.random() - 0.5;
-				directionalLight.position.y = Math.random();
-				directionalLight.position.z = Math.random() - 0.5;
+				directionalLight.position.set( 1, 1, - 1 );
 				directionalLight.position.normalize();
 				scene.add( directionalLight );
 
-				// Renderer
+				//
+
 				renderer = new THREE.WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 
-				// Stats
+				//
+
 				stats = new Stats();
 				container.appendChild( stats.dom );
 
-				// Events
+				//
+
 				window.addEventListener( 'resize', onWindowResize, false );
 
 			}
 
 			//
 
-			function onWindowResize( event ) {
+			function onWindowResize() {
 
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
@@ -156,7 +147,6 @@
 
 			//
 
-			var t = 0;
 			function animate() {
 
 				requestAnimationFrame( animate );
@@ -169,11 +159,11 @@
 
 			function render() {
 
-				var timer = Date.now() * 0.0005;
+				var elapsedTime = clock.getElapsedTime();
 
-				camera.position.x = Math.cos( timer ) * 10;
+				camera.position.x = Math.cos( elapsedTime * 0.5 ) * 10;
 				camera.position.y = 4;
-				camera.position.z = Math.sin( timer ) * 10;
+				camera.position.z = Math.sin( elapsedTime * 0.5 ) * 10;
 
 				camera.lookAt( scene.position );