Browse Source

GeometryLoader working (ex JSONLoader)
Tried to make it as straight foward as possible. Kept the extrac base url thingie :)
Thinking of moving BinaryLoader to examples/js/loaders.... what do you think @alteredq?

Mr.doob 13 years ago
parent
commit
e4dc8cfe89

+ 9 - 6
examples/canvas_geometry_earth.html

@@ -41,7 +41,7 @@
 
 			var container, stats;
 			var camera, scene, renderer;
-			var mesh;
+			var group;
 			var mouseX = 0, mouseY = 0;
 
 			var windowHalfX = window.innerWidth / 2;
@@ -60,6 +60,9 @@
 				camera.position.z = 500;
 				scene.add( camera );
 
+				group = new THREE.Object3D();
+				scene.add( group );
+
 				// earth
 				
 				var earthTexture = new THREE.Texture();
@@ -77,8 +80,8 @@
 				var geometry = new THREE.SphereGeometry( 200, 20, 20 );
 				var material = new THREE.MeshBasicMaterial( { map: earthTexture, overdraw: true } );
 
-				mesh = new THREE.Mesh( geometry, material );
-				scene.add( mesh );
+				var mesh = new THREE.Mesh( geometry, material );
+				group.add( mesh );
 
 				// shadow
 				
@@ -97,9 +100,9 @@
 				var geometry = new THREE.PlaneGeometry( 300, 300, 3, 3 );
 				var material = new THREE.MeshBasicMaterial( { map: shadowTexture, overdraw: true } );
 
-				mesh = new THREE.Mesh( geometry, material );
+				var mesh = new THREE.Mesh( geometry, material );
 				mesh.position.y = - 250;
-				scene.add( mesh );
+				group.add( mesh );
 
 				renderer = new THREE.CanvasRenderer();
 				renderer.setSize( window.innerWidth, window.innerHeight );
@@ -139,7 +142,7 @@
 				camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
 				camera.lookAt( scene.position );
 
-				mesh.rotation.y -= 0.005;
+				group.rotation.y -= 0.005;
 
 				renderer.render( scene, camera );
 

+ 7 - 2
examples/webgl_loader_json_blender.html

@@ -34,6 +34,8 @@
 
 		<script src="../build/Three.js"></script>
 
+		<script src="../src/loaders/GeometryLoader.js"></script>
+
 		<script src="js/loaders/ColladaLoader.js"></script>
 
 		<script src="js/Detector.js"></script>
@@ -85,8 +87,10 @@
 
 				// Add Blender exported Collada model
 
-				var loader = new THREE.JSONLoader();
-				loader.load( "models/animated/monster/monster.js", function ( geometry ) {
+				var loader = new THREE.GeometryLoader();
+				loader.addEventListener( 'load', function ( event ) {
+
+					var geometry = event.content;
 
 					// adjust color a bit
 
@@ -134,6 +138,7 @@
 					}
 
 				} );
+				loader.load( 'models/animated/monster/monster.js' );
 
 
 				// Add the COLLADA

+ 643 - 0
src/loaders/GeometryLoader.js

@@ -0,0 +1,643 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.GeometryLoader = function () {
+
+	THREE.EventTarget.call( this );
+
+};
+
+THREE.GeometryLoader.prototype = {
+
+	constructor: THREE.GeometryLoader,
+
+	crossOrigin: null,
+
+	path: null,
+
+	load: function ( url ) {
+
+		var scope = this;
+
+		if ( scope.path === null ) {
+
+			var parts = url.split( '/' ); parts.pop();
+			scope.path = ( parts.length < 1 ? '.' : parts.join( '/' ) );
+
+		}
+
+		var xhr = new XMLHttpRequest();
+
+		xhr.addEventListener( 'load', function ( event ) {
+
+			if ( event.target.responseText ) {
+
+				scope.dispatchEvent( { type: 'load', content: scope.parse( JSON.parse( event.target.responseText ) ) } );
+
+			} else {
+
+				scope.dispatchEvent( { type: 'error', message: 'URL unreachable or empty file [' + url + ']' } );
+
+			}
+
+		}, false );
+
+		xhr.addEventListener( 'progress', function ( event ) {
+
+			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
+
+		}, false );
+
+		xhr.addEventListener( 'error', function () {
+
+			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
+
+		}, false );
+
+		xhr.open( 'GET', url, true );
+		xhr.send( null );
+
+	},
+
+	parse: function ( data ) {
+
+		var scope = this;
+		var geometry = new THREE.Geometry();
+
+		var scale = ( data.scale !== undefined ) ? 1 / data.scale : 1;
+
+		// materials
+
+		geometry.materials = [];
+
+		for ( var i = 0; i < data.materials.length; ++ i ) {
+
+			var m = data.materials[ i ];
+
+			function isPow2( n ) {
+
+				var l = Math.log( n ) / Math.LN2;
+				return Math.floor( l ) == l;
+
+			}
+
+			function nearestPow2( n ) {
+
+				var l = Math.log( n ) / Math.LN2;
+				return Math.pow( 2, Math.round(  l ) );
+
+			}
+
+			function createTexture( where, name, sourceFile, repeat, offset, wrap ) {
+
+				where[ name ] = new THREE.Texture();
+				where[ name ].sourceFile = sourceFile;
+
+				if ( repeat ) {
+
+					where[ name ].repeat.set( repeat[ 0 ], repeat[ 1 ] );
+
+					if ( repeat[ 0 ] != 1 ) where[ name ].wrapS = THREE.RepeatWrapping;
+					if ( repeat[ 1 ] != 1 ) where[ name ].wrapT = THREE.RepeatWrapping;
+
+				}
+
+				if ( offset ) {
+
+					where[ name ].offset.set( offset[ 0 ], offset[ 1 ] );
+
+				}
+
+				if ( wrap ) {
+
+					var wrapMap = {
+
+						"repeat": THREE.RepeatWrapping,
+						"mirror": THREE.MirroredRepeatWrapping
+
+					}
+
+					if ( wrapMap[ wrap[ 0 ] ] !== undefined ) where[ name ].wrapS = wrapMap[ wrap[ 0 ] ];
+					if ( wrapMap[ wrap[ 1 ] ] !== undefined ) where[ name ].wrapT = wrapMap[ wrap[ 1 ] ];
+
+				}
+
+				// load image
+
+				var texture = where[ name ];
+
+				var loader = new THREE.ImageLoader();
+				loader.addEventListener( 'load', function ( event ) {
+
+					var image = event.content;
+
+					if ( !isPow2( image.width ) || !isPow2( image.height ) ) {
+
+						var width = nearestPow2( image.width );
+						var height = nearestPow2( image.height );
+
+						texture.image = document.createElement( 'canvas' );
+						texture.image.width = width;
+						texture.image.height = height;
+						texture.image.getContext( '2d' ).drawImage( image, 0, 0, width, height );
+
+					} else {
+
+						texture.image = image;
+
+					}
+
+					texture.needsUpdate = true;
+
+				} );
+				loader.crossOrigin = scope.crossOrigin;
+				loader.load( scope.path + '/' + sourceFile );
+
+			}
+
+			function rgb2hex( rgb ) {
+
+				return ( rgb[ 0 ] * 255 << 16 ) + ( rgb[ 1 ] * 255 << 8 ) + rgb[ 2 ] * 255;
+
+			}
+
+			// defaults
+
+			var mtype = "MeshLambertMaterial";
+			var mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, normalMap: null, wireframe: m.wireframe };
+
+			// parameters from model file
+
+			if ( m.shading ) {
+
+				var shading = m.shading.toLowerCase();
+
+				if ( shading === "phong" ) mtype = "MeshPhongMaterial";
+				else if ( shading === "basic" ) mtype = "MeshBasicMaterial";
+
+			}
+
+			if ( m.blending !== undefined && THREE[ m.blending ] !== undefined ) {
+
+				mpars.blending = THREE[ m.blending ];
+
+			}
+
+			if ( m.transparent !== undefined || m.opacity < 1.0 ) {
+
+				mpars.transparent = m.transparent;
+
+			}
+
+			if ( m.depthTest !== undefined ) {
+
+				mpars.depthTest = m.depthTest;
+
+			}
+
+			if ( m.depthWrite !== undefined ) {
+
+				mpars.depthWrite = m.depthWrite;
+
+			}
+
+			if ( m.vertexColors !== undefined ) {
+
+				if ( m.vertexColors == "face" ) {
+
+					mpars.vertexColors = THREE.FaceColors;
+
+				} else if ( m.vertexColors ) {
+
+					mpars.vertexColors = THREE.VertexColors;
+
+				}
+
+			}
+
+			// colors
+
+			if ( m.colorDiffuse ) {
+
+				mpars.color = rgb2hex( m.colorDiffuse );
+
+			} else if ( m.DbgColor ) {
+
+				mpars.color = m.DbgColor;
+
+			}
+
+			if ( m.colorSpecular ) {
+
+				mpars.specular = rgb2hex( m.colorSpecular );
+
+			}
+
+			if ( m.colorAmbient ) {
+
+				mpars.ambient = rgb2hex( m.colorAmbient );
+
+			}
+
+			// modifiers
+
+			if ( m.transparency ) {
+
+				mpars.opacity = m.transparency;
+
+			}
+
+			if ( m.specularCoef ) {
+
+				mpars.shininess = m.specularCoef;
+
+			}
+
+			// textures
+
+			if ( m.mapDiffuse ) {
+
+				createTexture( mpars, "map", m.mapDiffuse, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap );
+
+			}
+
+			if ( m.mapLight ) {
+
+				createTexture( mpars, "lightMap", m.mapLight, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap );
+
+			}
+
+			if ( m.mapNormal ) {
+
+				createTexture( mpars, "normalMap", m.mapNormal, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap );
+
+			}
+
+			if ( m.mapSpecular ) {
+
+				createTexture( mpars, "specularMap", m.mapSpecular, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap );
+
+			}
+
+			// special case for normal mapped material
+
+			if ( m.mapNormal ) {
+
+				var shader = THREE.ShaderUtils.lib[ "normal" ];
+				var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
+
+				uniforms[ "tNormal" ].texture = mpars.normalMap;
+
+				if ( m.mapNormalFactor ) {
+
+					uniforms[ "uNormalScale" ].value = m.mapNormalFactor;
+
+				}
+
+				if ( mpars.map ) {
+
+					uniforms[ "tDiffuse" ].texture = mpars.map;
+					uniforms[ "enableDiffuse" ].value = true;
+
+				}
+
+				if ( mpars.specularMap ) {
+
+					uniforms[ "tSpecular" ].texture = mpars.specularMap;
+					uniforms[ "enableSpecular" ].value = true;
+
+				}
+
+				if ( mpars.lightMap ) {
+
+					uniforms[ "tAO" ].texture = mpars.lightMap;
+					uniforms[ "enableAO" ].value = true;
+
+				}
+
+				// for the moment don't handle displacement texture
+
+				uniforms[ "uDiffuseColor" ].value.setHex( mpars.color );
+				uniforms[ "uSpecularColor" ].value.setHex( mpars.specular );
+				uniforms[ "uAmbientColor" ].value.setHex( mpars.ambient );
+
+				uniforms[ "uShininess" ].value = mpars.shininess;
+
+				if ( mpars.opacity !== undefined ) {
+
+					uniforms[ "uOpacity" ].value = mpars.opacity;
+
+				}
+
+				var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };
+				var material = new THREE.ShaderMaterial( parameters );
+
+			} else {
+
+				var material = new THREE[ mtype ]( mpars );
+
+			}
+
+			if ( m.DbgName !== undefined ) material.name = m.DbgName;
+
+			geometry.materials[ i ] = material;
+
+		}
+
+
+		// geometry
+
+		function isBitSet( value, position ) {
+
+			return value & ( 1 << position );
+
+		}
+	
+		var faces = data.faces;
+		var vertices = data.vertices;
+		var normals = data.normals;
+		var colors = data.colors;
+		var nUvLayers = 0;
+
+		// disregard empty arrays
+
+		for ( var i = 0; i < data.uvs.length; i ++ ) {
+
+			if ( data.uvs[ i ].length ) nUvLayers ++;
+
+		}
+
+		for ( var i = 0; i < nUvLayers; i ++ ) {
+
+			geometry.faceUvs[ i ] = [];
+			geometry.faceVertexUvs[ i ] = [];
+
+		}
+
+		var offset = 0;
+		var zLength = vertices.length;
+
+		while ( offset < zLength ) {
+
+			var vertex = new THREE.Vector3();
+
+			vertex.x = vertices[ offset ++ ] * scale;
+			vertex.y = vertices[ offset ++ ] * scale;
+			vertex.z = vertices[ offset ++ ] * scale;
+
+			geometry.vertices.push( vertex );
+
+		}
+
+		offset = 0;
+		zLength = faces.length;
+
+		while ( offset < zLength ) {
+
+			var type = faces[ offset ++ ];
+
+			var isQuad = isBitSet( type, 0 );
+
+			var hasMaterial = isBitSet( type, 1 );
+			var hasFaceUv = isBitSet( type, 2 );
+			var hasFaceVertexUv = isBitSet( type, 3 );
+			var hasFaceNormal = isBitSet( type, 4 );
+			var hasFaceVertexNormal = isBitSet( type, 5 );
+			var hasFaceColor = isBitSet( type, 6 );
+			var hasFaceVertexColor = isBitSet( type, 7 );
+
+			// console.log("type", type, "bits", isQuad, hasMaterial, hasFaceUv, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
+
+			if ( isQuad ) {
+
+				var face = new THREE.Face4();
+
+				face.a = faces[ offset ++ ];
+				face.b = faces[ offset ++ ];
+				face.c = faces[ offset ++ ];
+				face.d = faces[ offset ++ ];
+
+				var nVertices = 4;
+
+			} else {
+
+				var face = new THREE.Face3();
+
+				face.a = faces[ offset ++ ];
+				face.b = faces[ offset ++ ];
+				face.c = faces[ offset ++ ];
+
+				var nVertices = 3;
+
+			}
+
+			if ( hasMaterial ) {
+
+				var materialIndex = faces[ offset ++ ];
+				face.materialIndex = materialIndex;
+
+			}
+
+			// to get face <=> uv index correspondence
+
+			var fi = geometry.faces.length;
+
+			if ( hasFaceUv ) {
+
+				for ( var i = 0; i < nUvLayers; i ++ ) {
+
+					var uvLayer = data.uvs[ i ];
+
+					var uvIndex = faces[ offset ++ ];
+
+					var u = uvLayer[ uvIndex * 2 ];
+					var v = uvLayer[ uvIndex * 2 + 1 ];
+
+					geometry.faceUvs[ i ][ fi ] = new THREE.UV( u, v );
+
+				}
+
+			}
+
+			if ( hasFaceVertexUv ) {
+
+				for ( var i = 0; i < nUvLayers; i ++ ) {
+
+					var uvLayer = data.uvs[ i ];
+
+					var uvs = [];
+
+					for ( var j = 0; j < nVertices; j ++ ) {
+
+						var uvIndex = faces[ offset ++ ];
+
+						var u = uvLayer[ uvIndex * 2 ];
+						var v = uvLayer[ uvIndex * 2 + 1 ];
+
+						uvs[ j ] = new THREE.UV( u, v );
+
+					}
+
+					geometry.faceVertexUvs[ i ][ fi ] = uvs;
+
+				}
+
+			}
+
+			if ( hasFaceNormal ) {
+
+				var normalIndex = faces[ offset ++ ] * 3;
+
+				var normal = new THREE.Vector3();
+
+				normal.x = normals[ normalIndex ++ ];
+				normal.y = normals[ normalIndex ++ ];
+				normal.z = normals[ normalIndex ];
+
+				face.normal = normal;
+
+			}
+
+			if ( hasFaceVertexNormal ) {
+
+				for ( i = 0; i < nVertices; i ++ ) {
+
+					var normalIndex = faces[ offset ++ ] * 3;
+
+					var normal = new THREE.Vector3();
+
+					normal.x = normals[ normalIndex ++ ];
+					normal.y = normals[ normalIndex ++ ];
+					normal.z = normals[ normalIndex ];
+
+					face.vertexNormals.push( normal );
+
+				}
+
+			}
+
+
+			if ( hasFaceColor ) {
+
+				var colorIndex = faces[ offset ++ ];
+
+				face.color = new THREE.Color( colors[ colorIndex ] );
+
+			}
+
+
+			if ( hasFaceVertexColor ) {
+
+				for ( var i = 0; i < nVertices; i ++ ) {
+
+					var colorIndex = faces[ offset ++ ];
+
+					face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
+
+				}
+
+			}
+
+			geometry.faces.push( face );
+
+		}
+
+
+		// skin
+
+		if ( data.skinWeights ) {
+
+			for ( var i = 0, l = data.skinWeights.length; i < l; i += 2 ) {
+
+				var x = data.skinWeights[ i ];
+				var y = data.skinWeights[ i + 1 ];
+				var z = 0;
+				var w = 0;
+
+				geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
+
+			}
+
+		}
+
+		if ( data.skinIndices ) {
+
+			for ( var i = 0, l = data.skinIndices.length; i < l; i += 2 ) {
+
+				var a = data.skinIndices[ i ];
+				var b = data.skinIndices[ i + 1 ];
+				var c = 0;
+				var d = 0;
+
+				geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
+
+			}
+
+		}
+
+		geometry.bones = data.bones;
+		geometry.animation = data.animation;
+
+
+		// morphing
+
+		if ( data.morphTargets !== undefined ) {
+
+			for ( var i = 0, l = data.morphTargets.length; i < l; i ++ ) {
+
+				geometry.morphTargets[ i ] = {};
+				geometry.morphTargets[ i ].name = data.morphTargets[ i ].name;
+				geometry.morphTargets[ i ].vertices = [];
+
+				var dstVertices = geometry.morphTargets[ i ].vertices;
+				var srcVertices = data.morphTargets [ i ].vertices;
+
+				for( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
+
+					var vertex = new THREE.Vector3();
+					vertex.x = srcVertices[ v ] * scale;
+					vertex.y = srcVertices[ v + 1 ] * scale;
+					vertex.z = srcVertices[ v + 2 ] * scale;
+
+					dstVertices.push( vertex );
+
+				}
+
+			}
+
+		}
+
+		if ( data.morphColors !== undefined ) {
+
+			for ( var i = 0, l = data.morphColors.length; i < l; i++ ) {
+
+				geometry.morphColors[ i ] = {};
+				geometry.morphColors[ i ].name = data.morphColors[ i ].name;
+				geometry.morphColors[ i ].colors = [];
+
+				var dstColors = geometry.morphColors[ i ].colors;
+				var srcColors = data.morphColors [ i ].colors;
+
+				for ( var c = 0, cl = srcColors.length; c < cl; c += 3 ) {
+
+					var color = new THREE.Color( 0xffaa00 );
+					color.setRGB( srcColors[ c ], srcColors[ c + 1 ], srcColors[ c + 2 ] );
+
+					dstColors.push( color );
+
+				}
+
+			}
+
+		}
+
+		geometry.computeCentroids();
+		geometry.computeFaceNormals();
+
+		return geometry;
+
+	}
+
+};

+ 2 - 2
src/loaders/ImageLoader.js

@@ -12,7 +12,7 @@ THREE.ImageLoader.prototype = {
 
 	constructor: THREE.ImageLoader,
 
-	crossOrigin: 'anonymous',
+	crossOrigin: null,
 
 	load: function ( url ) {
 
@@ -31,7 +31,7 @@ THREE.ImageLoader.prototype = {
 		
 		}, false );
 
-		image.crossOrigin = this.crossOrigin;
+		if ( scope.crossOrigin ) image.crossOrigin = scope.crossOrigin;
 		image.src = url;
 
 	}