Browse Source

Created MD2Loader. Forcing it to little-endian by now.

Mr.doob 10 years ago
parent
commit
7021f821e1
1 changed files with 180 additions and 0 deletions
  1. 180 0
      examples/js/loaders/MD2Loader.js

+ 180 - 0
examples/js/loaders/MD2Loader.js

@@ -0,0 +1,180 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.MD2Loader = function ( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+
+};
+
+THREE.MD2Loader.prototype = {
+
+	constructor: THREE.MD2Loader,
+
+	load: function ( url, onLoad, onProgress, onError ) {
+
+		var scope = this;
+
+		var loader = new THREE.XHRLoader( scope.manager );
+		loader.setCrossOrigin( this.crossOrigin );
+		loader.setResponseType( 'arraybuffer' );
+		loader.load( url, function ( buffer ) {
+
+			onLoad( scope.parse( buffer ) );
+
+		}, onProgress, onError );
+
+	},
+
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
+	},
+
+	parse: function ( buffer ) {
+
+		var data = new DataView( buffer );
+
+		// http://tfc.duke.free.fr/coding/md2-specs-en.html
+
+		var header = {};
+		var headerNames = [
+			'ident', 'version',
+			'skinwidth', 'skinheight',
+			'framesize',
+			'num_skins', 'num_vertices', 'num_st', 'num_tris', 'num_glcmds', 'num_frames',
+			'offset_skins', 'offset_st', 'offset_tris', 'offset_frames', 'offset_glcmds', 'offset_end'
+		];
+
+		for ( var i = 0; i < headerNames.length; i ++ ) {
+
+			header[ headerNames[ i ] ] = data.getInt32( i * 4, true );
+
+		}
+
+		if ( header.ident !== 844121161 || header.version !== 8 ) {
+
+			console.error( 'Not a valid MD2 file' );
+			return;
+
+		}
+
+		if ( header.offset_end !== data.byteLength ) {
+
+			console.error( 'Corrupted MD2 file' );
+			return;
+
+		}
+
+		//
+
+		var geometry = new THREE.Geometry();
+
+		// uvs
+
+		var uvs = [];
+		var offset = header.offset_st;
+
+		for ( var i = 0; i < header.num_st; i ++, offset += 4 ) {
+
+			var u = data.getInt16( offset + 0, true );
+			var v = data.getInt16( offset + 2, true );
+
+			var uv = new THREE.Vector2( u / header.skinwidth, 1 - ( v / header.skinheight ) );
+
+			uvs.push( uv );
+
+		}
+
+		// triangles
+
+		var offset = header.offset_tris;
+
+		for ( var i = 0; i < header.num_tris; i ++ ) {
+
+			var a = data.getUint16( offset + 0, true );
+			var b = data.getUint16( offset + 2, true );
+			var c = data.getUint16( offset + 4, true );
+
+			var face = new THREE.Face3( a, b, c );
+
+			geometry.faces.push( face );
+
+			geometry.faceVertexUvs[ 0 ].push( [
+				uvs[ data.getUint16( offset + 6, true ) ],
+				uvs[ data.getUint16( offset + 8, true ) ],
+				uvs[ data.getUint16( offset + 10, true ) ]
+			] );
+
+			offset += 12;
+
+		}
+
+		// frames
+
+		var translation = new THREE.Vector3();
+		var scale = new THREE.Vector3();
+
+		var offset = header.offset_frames;
+
+		for ( var i = 0; i < header.num_frames; i ++ ) {
+
+			scale.set(
+				data.getFloat32( offset + 0, true ),
+				data.getFloat32( offset + 4, true ),
+				data.getFloat32( offset + 8, true )
+			);
+
+			translation.set(
+				data.getFloat32( offset + 12, true ),
+				data.getFloat32( offset + 16, true ),
+				data.getFloat32( offset + 20, true )
+			);
+
+			offset += 24;
+
+			var string = [];
+
+			for ( var j = 0; j < 16; j ++ ) {
+
+				string[ j ] = data.getUint8( offset + j, true );
+
+			}
+
+			var frame = {
+				name: String.fromCharCode.apply( null, string ),
+				vertices: []
+			};
+
+			offset += 16;
+
+			for ( var j = 0; j < header.num_vertices; j ++ ) {
+
+				var x = data.getUint8( offset ++, true );
+				var y = data.getUint8( offset ++, true );
+				var z = data.getUint8( offset ++, true );
+				var n = data.getUint8( offset ++, true );
+
+				var vertex = new THREE.Vector3(
+					x * scale.x + translation.x,
+					z * scale.z + translation.z,
+					y * scale.y + translation.y
+				);
+
+				frame.vertices.push( vertex );
+
+			}
+
+			geometry.morphTargets.push( frame );
+
+		}
+
+		geometry.vertices = geometry.morphTargets[ 0 ].vertices;
+
+		return geometry;
+
+	}
+
+}