소스 검색

First version of JSONLoader.

It's not expected to work yet, we will need to test it once exporters / converters are also changed to new format.
alteredq 14 년 전
부모
커밋
fb95339301
1개의 변경된 파일452개의 추가작업 그리고 1개의 파일을 삭제
  1. 452 1
      src/extras/io/JSONLoader.js

+ 452 - 1
src/extras/io/JSONLoader.js

@@ -1,13 +1,464 @@
 /**
+ * @author mrdoob / http://mrdoob.com/
  * @author alteredq / http://alteredqualia.com/
  */
 
-THREE.JSONLoader = function () {
+THREE.JSONLoader = function ( showStatus ) {
 
 	THREE.Loader.call( this );
 
+	this.showStatus = showStatus;	
+	this.statusDomElement = showStatus ? this.addStatusElement() : null;
+	
 };
 
 THREE.JSONLoader.prototype = new THREE.Loader();
 THREE.JSONLoader.prototype.constructor = THREE.JSONLoader;
 THREE.JSONLoader.prototype.supr = THREE.Loader.prototype;
+
+
+THREE.JSONLoader.prototype = {
+
+	addStatusElement: function ( ) {
+		
+		var e = document.createElement( "div" );
+		
+		e.style.fontSize = "0.8em"; 
+		e.style.textAlign = "left";
+		e.style.background = "#b00"; 
+		e.style.color = "#fff"; 
+		e.style.width = "140px"; 
+		e.style.padding = "0.25em 0.25em 0.25em 0.5em"; 
+		e.style.position = "absolute"; 
+		e.style.right = "0px"; 
+		e.style.top = "0px"; 
+		e.style.zIndex = 1000;
+		
+		e.innerHTML = "Loading ...";
+		
+		return e;
+		
+	},
+	
+	updateProgress: function ( progress ) {
+
+		var message = "Loaded ";
+
+		if ( progress.total ) {
+
+			message += ( 100 * progress.loaded / progress.total ).toFixed(0) + "%";
+
+
+		} else {
+
+			message += ( progress.loaded / 1000 ).toFixed(2) + " KB";
+
+		}
+
+		this.statusDomElement.innerHTML = message;
+
+	},
+	
+
+	// Load models generated by slim OBJ converter with ASCII option (converter_obj_three_slim.py -t ascii)
+	//  - parameters
+	//		- model (required)
+	//		- callback (required)
+	//		- texture_path (optional: if not specified, textures will be assumed to be in the same folder as JS model file)
+
+	load: function ( parameters ) {
+
+		var url = parameters.model,
+			callback = parameters.callback, 
+		    texture_path = parameters.texture_path ? parameters.texture_path : THREE.JSONLoader.prototype.extractUrlbase( url ),
+		
+			s = (new Date).getTime(),
+			worker = new Worker( url );
+		
+		worker.onmessage = function( event ) {
+			
+			THREE.JSONLoader.prototype.createModel( event.data, callback, texture_path );
+
+		};
+
+		worker.postMessage( s );
+
+	},
+	
+	createModel: function ( json, callback, texture_path ) {
+
+		var Model = function ( texture_path ) {
+
+			var scope = this;
+
+			THREE.Geometry.call( this );
+
+			THREE.JSONLoader.prototype.init_materials( scope, json.materials, texture_path );
+
+			parse();
+			init_skin();
+
+			this.computeCentroids();
+			this.computeFaceNormals();
+			
+			function parse() {
+
+				if ( json.version === undefined || json.version != 2 ) {
+
+					console.error( 'Deprecated file format.' );
+					return;
+
+				}
+	
+				var i, j, 
+				
+				type, offset,
+
+				isTriangle, 
+				hasMaterial, 
+				hasFaceUv, hasFaceVertexUv,
+				hasFaceNormal, hasFaceVertexNormal,
+				hasFaceColor, hasFaceVertexColor,
+
+				vertex, face,
+				
+				faces = json.faces,
+				vertices = json.vertices,
+				normals = json.normals,
+
+				nUvLayers = json.uvs.length;
+
+				for ( i = 0; i < nUvLayers; i++ ) {
+
+					scope.faceUvs[ i ] = [];
+					scope.faceVertexUvs[ i ] = [];
+
+				}
+
+				offset = 0;
+
+				while ( vertices[ offset ] ) {
+
+					vertex = new THREE.Vertex();
+					
+					vertex.position.x = vertices[ offset ++ ];
+					vertex.position.y = vertices[ offset ++ ];
+					vertex.position.z = vertices[ offset ++ ];
+
+					scope.vertices.push( vertex );
+
+				}
+
+				offset = 0;
+
+				while ( faces[ offset ] ) {
+
+					type = faces[ offset ];
+
+					isTriangle          = isBitSet( type, 0 );
+					hasMaterial         = isBitSet( type, 1 );
+					hasFaceUv           = isBitSet( type, 2 );
+					hasFaceVertexUv     = isBitSet( type, 3 );
+					hasFaceNormal       = isBitSet( type, 4 );
+					hasFaceVertexNormal = isBitSet( type, 5 );
+					hasFaceColor	    = isBitSet( type, 6 );
+					hasFaceVertexColor  = isBitSet( type, 7 );
+
+
+					if ( isTriangle ) {
+
+						face = new THREE.Face3();
+					
+						face.a = faces[ offset ++ ];
+						face.b = faces[ offset ++ ];
+						face.c = faces[ offset ++ ];
+
+						nVertices = 3;
+
+					} else {
+
+						face = new THREE.Face4();
+						
+						face.a = faces[ offset ++ ];
+						face.b = faces[ offset ++ ];
+						face.c = faces[ offset ++ ];
+						face.d = faces[ offset ++ ];
+
+						nVertices = 4;
+
+					}
+
+					if ( hasMaterial ) {
+
+						materialIndex = faces[ offset ++ ];
+						face.materials = [ scope.materials[ materialIndex ] ];
+
+					}
+
+					if ( hasFaceUv ) {
+
+						for ( i = 0; i < nUvLayers; i++ ) {
+
+							uvLayer = json.uvs[ i ];
+
+							uvIndex = faces[ offset ++ ];
+
+							u = uvLayer[ uvIndex * 2 ];
+							v = uvLayer[ uvIndex * 2 + 1 ];
+
+							scope.faceUvs[ i ].push( new THREE.UV( u, v ) );
+
+						}
+
+					}
+
+					if ( hasFaceVertexUv ) {
+
+						for ( i = 0; i < nUvLayers; i++ ) {
+							
+							uvLayer = json.uvs[ i ];
+
+							uvs = [];
+
+							for ( j = 0; j < nVertices; j ++ ) {
+
+								uvIndex = faces[ offset ++ ];
+
+								u = uvLayer[ uvIndex * 2 ];
+								v = uvLayer[ uvIndex * 2 + 1 ];
+
+								uvs[ j ] = new THREE.UV( u, v );
+
+							}
+
+							scope.faceVertexUvs[ i ].push( uvs );
+
+						}
+
+					}
+
+					if ( hasFaceNormal ) {
+
+						normalIndex = faces[ offset ++ ] * 3;
+
+						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++ ) {
+
+							normalIndex = faces[ offset ++ ] * 3;
+
+							normal = new THREE.Vector3();
+							
+							normal.x = normals[ normalIndex ++ ];
+							normal.y = normals[ normalIndex ++ ];
+							normal.z = normals[ normalIndex ];
+
+							face.vertexNormals.push( normal );
+
+						}
+
+					}
+
+				
+					if ( hasFaceColor ) {
+
+						color = new THREE.Color( faces[ offset ++ ] );
+						face.color = color;
+
+					}
+
+					
+					if ( hasFaceVertexColor ) {
+
+						for ( i = 0; i < nVertices; i++ ) {
+
+							color = new THREE.Color( faces[ offset ++ ] );
+							face.vertexColors.push( color );
+
+						}
+
+					}
+
+					scope.faces.push( face );
+
+				}
+
+			};
+			
+			function init_skin() {
+				
+				var i, l, x, y, z, w, a, b, c, d;
+
+				if ( json.skinWeights ) {
+					
+					for( i = 0, l = json.skinWeights.length; i < l; i += 2 ) {
+
+						x = json.skinWeights[ i     ];
+						y = json.skinWeights[ i + 1 ];
+						z = 0;
+						w = 0;
+						
+						scope.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
+
+					}
+					
+				}
+				
+				if ( json.skinIndices ) {
+					
+					for( i = 0, l = json.skinIndices.length; i < l; i += 2 ) {
+
+						a = json.skinIndices[ i     ];
+						b = json.skinIndices[ i + 1 ];
+						c = 0;
+						d = 0;
+
+						scope.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
+
+					}
+				
+				}
+				
+				scope.bones = json.bones;
+				scope.animation = json.animation;
+				
+			};
+			
+			Model.prototype = new THREE.Geometry();
+			Model.prototype.constructor = Model;
+
+			callback( new Model( texture_path ) );
+
+		}
+
+	},		
+	
+	init_materials: function( scope, materials, texture_path ) {
+
+		scope.materials = [];
+
+		for ( var i = 0; i < materials.length; ++i ) {
+
+			scope.materials[ i ] = [ THREE.JSONLoader.prototype.createMaterial( materials[ i ], texture_path ) ];
+
+		}
+
+	},
+
+	createMaterial: function ( m, texture_path ) {
+
+		function is_pow2( n ) {
+
+			var l = Math.log(n) / Math.LN2;
+			return Math.floor(l) == l;
+
+		}
+
+		function nearest_pow2( n ) {
+
+			var l = Math.log(n) / Math.LN2;
+			return Math.pow( 2, Math.round(l) );
+
+		}
+
+		function load_image( where, url ) {
+			
+			var image = new Image();
+			
+			image.onload = function () {
+
+				if ( !is_pow2( this.width ) || !is_pow2( this.height ) ) {
+
+					var w = nearest_pow2( this.width ),
+						h = nearest_pow2( this.height );
+
+					where.image.width = w;
+					where.image.height = h;
+					where.image.getContext("2d").drawImage( this, 0, 0, w, h );
+
+				} else {
+
+					where.image = this;
+
+				}
+
+				where.needsUpdate = true;
+
+			};
+
+			image.src = url;
+			
+		}
+		
+		var material, mtype, mpars, texture, color;
+
+		// defaults
+		
+		mtype = "MeshLambertMaterial";
+		mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, vertexColors: m.vertexColors };
+		
+		// parameters from model file
+		
+		if ( m.shading ) {
+			
+			if ( m.shading == "Phong" ) mtype = "MeshPhongMaterial";
+			
+		}
+		
+		if ( m.mapDiffuse && texture_path ) {
+
+			texture = document.createElement( 'canvas' );
+			
+			mpars.map = new THREE.Texture( texture );
+			mpars.map.sourceFile = m.mapDiffuse;
+			
+			load_image( mpars.map, texture_path + "/" + m.mapDiffuse );
+
+		} else if ( m.colorDiffuse ) {
+
+			color = ( m.colorDiffuse[0] * 255 << 16 ) + ( m.colorDiffuse[1] * 255 << 8 ) + m.colorDiffuse[2] * 255;
+			mpars.color = color;
+			mpars.opacity =  m.transparency;
+
+		} else if ( m.DbgColor ) {
+
+			mpars.color = m.DbgColor;
+
+		}
+
+		if ( m.mapLightmap && texture_path ) {
+
+			texture = document.createElement( 'canvas' );
+			
+			mpars.lightMap = new THREE.Texture( texture );
+			mpars.lightMap.sourceFile = m.mapLightmap;
+			
+			load_image( mpars.lightMap, texture_path + "/" + m.mapLightmap );
+
+		}
+		
+		material = new THREE[ mtype ]( mpars );
+
+		return material;
+
+	},
+	
+	extractUrlbase: function( url ) {
+		
+		var chunks = url.split( "/" );
+		chunks.pop();
+		return chunks.join( "/" );
+		
+	}
+
+};