OBJLoader.js 6.5 KB
Newer Older
M
Mr.doob 已提交
1 2 3 4
/**
 * @author mrdoob / http://mrdoob.com/
 */

M
r59  
Mr.doob 已提交
5 6 7 8 9
THREE.OBJLoader = function ( manager ) {

	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

};
M
Mr.doob 已提交
10 11 12 13 14

THREE.OBJLoader.prototype = {

	constructor: THREE.OBJLoader,

M
r59  
Mr.doob 已提交
15
	load: function ( url, onLoad, onProgress, onError ) {
M
Mr.doob 已提交
16 17 18

		var scope = this;

M
r59  
Mr.doob 已提交
19 20 21
		var loader = new THREE.XHRLoader( scope.manager );
		loader.setCrossOrigin( this.crossOrigin );
		loader.load( url, function ( text ) {
M
Mr.doob 已提交
22

M
r59  
Mr.doob 已提交
23
			onLoad( scope.parse( text ) );
M
Mr.doob 已提交
24

M
r59  
Mr.doob 已提交
25
		} );
M
Mr.doob 已提交
26 27 28

	},

M
r61  
Mr.doob 已提交
29
	parse: function ( text ) {
M
Mr.doob 已提交
30 31 32

		// fixes

M
r61  
Mr.doob 已提交
33
		text = text.replace( /\ \\\r\n/g, '' ); // rhino adds ' \\r\n' some times.
M
Mr.doob 已提交
34

M
r60  
Mr.doob 已提交
35
		var replacement = '/f$1$2$4\n/f$2$3$4'; // quads to tris
M
r61  
Mr.doob 已提交
36 37 38 39
		text = text.replace( /f( +\d+)( +\d+)( +\d+)( +\d+)/g, replacement );
		text = text.replace( /f( +\d+\/\d+)( +\d+\/\d+)( +\d+\/\d+)( +\d+\/\d+)/g, replacement );
		text = text.replace( /f( +\d+\/\d+\/\d+)( +\d+\/\d+\/\d+)( +\d+\/\d+\/\d+)( +\d+\/\d+\/\d+)/g, replacement );
		text = text.replace( /f( +\d+\/\/\d+)( +\d+\/\/\d+)( +\d+\/\/\d+)( +\d+\/\/\d+)/g, replacement );
M
r60  
Mr.doob 已提交
40

M
Mr.doob 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
		//

		function vector( x, y, z ) {

			return new THREE.Vector3( x, y, z );

		}

		function uv( u, v ) {

			return new THREE.Vector2( u, v );

		}

		function face3( a, b, c, normals ) {

			return new THREE.Face3( a, b, c, normals );

		}

M
r61  
Mr.doob 已提交
61 62
		var object = new THREE.Object3D();
		var geometry, material, mesh;
M
Mr.doob 已提交
63

M
r61  
Mr.doob 已提交
64
		// create mesh if no objects in text
M
Mr.doob 已提交
65

M
r61  
Mr.doob 已提交
66
		if ( /^o /gm.test( text ) === false ) {
M
Mr.doob 已提交
67

M
r61  
Mr.doob 已提交
68 69 70 71
			geometry = new THREE.Geometry();
			material = new THREE.MeshLambertMaterial();
			mesh = new THREE.Mesh( geometry, material );
			object.add( mesh );
M
Mr.doob 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

		}

		var vertices = [];
		var verticesCount = 0;
		var normals = [];
		var uvs = [];

		// v float float float

		var vertex_pattern = /v( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/;

		// vn float float float

		var normal_pattern = /vn( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/;

		// vt float float

M
r61  
Mr.doob 已提交
90
		var uv_pattern = /vt( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/;
M
Mr.doob 已提交
91

M
r60  
Mr.doob 已提交
92
		// f vertex vertex vertex
M
Mr.doob 已提交
93

M
r61  
Mr.doob 已提交
94
		var face_pattern1 = /f( +\d+)( +\d+)( +\d+)/;
M
Mr.doob 已提交
95

M
r60  
Mr.doob 已提交
96
		// f vertex/uv vertex/uv vertex/uv
M
Mr.doob 已提交
97

M
r60  
Mr.doob 已提交
98
		var face_pattern2 = /f( +(\d+)\/(\d+))( +(\d+)\/(\d+))( +(\d+)\/(\d+))/;
M
Mr.doob 已提交
99

M
r60  
Mr.doob 已提交
100
		// f vertex/uv/normal vertex/uv/normal vertex/uv/normal
M
Mr.doob 已提交
101

M
r60  
Mr.doob 已提交
102
		var face_pattern3 = /f( +(\d+)\/(\d+)\/(\d+))( +(\d+)\/(\d+)\/(\d+))( +(\d+)\/(\d+)\/(\d+))/;
M
Mr.doob 已提交
103

M
r60  
Mr.doob 已提交
104
		// f vertex//normal vertex//normal vertex//normal
M
Mr.doob 已提交
105

M
r60  
Mr.doob 已提交
106
		var face_pattern4 = /f( +(\d+)\/\/(\d+))( +(\d+)\/\/(\d+))( +(\d+)\/\/(\d+))/;
M
Mr.doob 已提交
107 108 109

		//

M
r61  
Mr.doob 已提交
110
		var lines = text.split( '\n' );
M
Mr.doob 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

		for ( var i = 0; i < lines.length; i ++ ) {

			var line = lines[ i ];
			line = line.trim();

			var result;

			if ( line.length === 0 || line.charAt( 0 ) === '#' ) {

				continue;

			} else if ( ( result = vertex_pattern.exec( line ) ) !== null ) {

				// ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]

				vertices.push( vector(
					parseFloat( result[ 1 ] ),
					parseFloat( result[ 2 ] ),
					parseFloat( result[ 3 ] )
				) );

			} else if ( ( result = normal_pattern.exec( line ) ) !== null ) {

				// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]

				normals.push( vector(
					parseFloat( result[ 1 ] ),
					parseFloat( result[ 2 ] ),
					parseFloat( result[ 3 ] )
				) );

			} else if ( ( result = uv_pattern.exec( line ) ) !== null ) {

				// ["vt 0.1 0.2", "0.1", "0.2"]

				uvs.push( uv(
					parseFloat( result[ 1 ] ),
					parseFloat( result[ 2 ] )
				) );

			} else if ( ( result = face_pattern1.exec( line ) ) !== null ) {

M
r60  
Mr.doob 已提交
154
				// ["f 1 2 3", "1", "2", "3"]
M
Mr.doob 已提交
155

M
r60  
Mr.doob 已提交
156 157 158 159 160
				geometry.vertices.push(
					vertices[ parseInt( result[ 1 ] ) - 1 ],
					vertices[ parseInt( result[ 2 ] ) - 1 ],
					vertices[ parseInt( result[ 3 ] ) - 1 ]
				);
M
Mr.doob 已提交
161

M
r60  
Mr.doob 已提交
162 163 164 165 166
				geometry.faces.push( face3(
					verticesCount ++,
					verticesCount ++,
					verticesCount ++
				) );
M
Mr.doob 已提交
167

M
r60  
Mr.doob 已提交
168
			} else if ( ( result = face_pattern2.exec( line ) ) !== null ) {
M
Mr.doob 已提交
169

M
r60  
Mr.doob 已提交
170
				// ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3"]
M
Mr.doob 已提交
171

M
r60  
Mr.doob 已提交
172 173 174 175 176
				geometry.vertices.push(
					vertices[ parseInt( result[ 2 ] ) - 1 ],
					vertices[ parseInt( result[ 5 ] ) - 1 ],
					vertices[ parseInt( result[ 8 ] ) - 1 ]
				);
M
Mr.doob 已提交
177

M
r60  
Mr.doob 已提交
178 179 180 181 182
				geometry.faces.push( face3(
					verticesCount ++,
					verticesCount ++,
					verticesCount ++
				) );
M
Mr.doob 已提交
183

M
r60  
Mr.doob 已提交
184 185 186 187 188
				geometry.faceVertexUvs[ 0 ].push( [
					uvs[ parseInt( result[ 3 ] ) - 1 ],
					uvs[ parseInt( result[ 6 ] ) - 1 ],
					uvs[ parseInt( result[ 9 ] ) - 1 ]
				] );
M
Mr.doob 已提交
189 190 191

			} else if ( ( result = face_pattern3.exec( line ) ) !== null ) {

M
r60  
Mr.doob 已提交
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
				// ["f 1/1/1 2/2/2 3/3/3", " 1/1/1", "1", "1", "1", " 2/2/2", "2", "2", "2", " 3/3/3", "3", "3", "3"]

				geometry.vertices.push(
					vertices[ parseInt( result[ 2 ] ) - 1 ],
					vertices[ parseInt( result[ 6 ] ) - 1 ],
					vertices[ parseInt( result[ 10 ] ) - 1 ]
				);

				geometry.faces.push( face3(
					verticesCount ++,
					verticesCount ++,
					verticesCount ++,
					[
						normals[ parseInt( result[ 4 ] ) - 1 ],
						normals[ parseInt( result[ 8 ] ) - 1 ],
						normals[ parseInt( result[ 12 ] ) - 1 ]
					]
				) );

				geometry.faceVertexUvs[ 0 ].push( [
					uvs[ parseInt( result[ 3 ] ) - 1 ],
					uvs[ parseInt( result[ 7 ] ) - 1 ],
					uvs[ parseInt( result[ 11 ] ) - 1 ]
				] );
M
Mr.doob 已提交
216 217 218

			} else if ( ( result = face_pattern4.exec( line ) ) !== null ) {

M
r60  
Mr.doob 已提交
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
				// ["f 1//1 2//2 3//3", " 1//1", "1", "1", " 2//2", "2", "2", " 3//3", "3", "3"]

				geometry.vertices.push(
					vertices[ parseInt( result[ 2 ] ) - 1 ],
					vertices[ parseInt( result[ 5 ] ) - 1 ],
					vertices[ parseInt( result[ 8 ] ) - 1 ]
				);

				geometry.faces.push( face3(
					verticesCount ++,
					verticesCount ++,
					verticesCount ++,
					[
						normals[ parseInt( result[ 3 ] ) - 1 ],
						normals[ parseInt( result[ 6 ] ) - 1 ],
						normals[ parseInt( result[ 9 ] ) - 1 ]
					]
				) );
M
Mr.doob 已提交
237 238 239 240 241

			} else if ( /^o /.test( line ) ) {

				// object

M
r61  
Mr.doob 已提交
242 243 244 245 246 247 248 249
				geometry = new THREE.Geometry();
				material = new THREE.MeshLambertMaterial();

				mesh = new THREE.Mesh( geometry, material );
				mesh.name = line.substring( 2 ).trim();
				object.add( mesh );

				verticesCount = 0;
M
Mr.doob 已提交
250 251 252 253 254 255 256 257 258

			} else if ( /^g /.test( line ) ) {

				// group

			} else if ( /^usemtl /.test( line ) ) {

				// material

M
r61  
Mr.doob 已提交
259
				material.name = line.substring( 7 ).trim();
M
Mr.doob 已提交
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276

			} else if ( /^mtllib /.test( line ) ) {

				// mtl file

			} else if ( /^s /.test( line ) ) {

				// smooth shading

			} else {

				// console.log( "THREE.OBJLoader: Unhandled line " + line );

			}

		}

M
r61  
Mr.doob 已提交
277 278 279 280 281 282 283 284 285
		for ( var i = 0, l = object.children.length; i < l; i ++ ) {

			var geometry = object.children[ i ].geometry;

			geometry.computeCentroids();
			geometry.computeFaceNormals();
			geometry.computeBoundingSphere();

		}
M
Mr.doob 已提交
286

M
r61  
Mr.doob 已提交
287
		return object;
M
Mr.doob 已提交
288 289 290

	}

M
r58  
Mr.doob 已提交
291
};