|
@@ -28,133 +28,165 @@ THREE.OBJLoader.prototype = {
|
|
|
|
|
|
parse: function ( text ) {
|
|
|
|
|
|
- function vector( x, y, z ) {
|
|
|
+ console.time( 'OBJLoader' );
|
|
|
|
|
|
- return new THREE.Vector3( parseFloat( x ), parseFloat( y ), parseFloat( z ) );
|
|
|
+ var object, objects = [];
|
|
|
+ var geometry, material, mesh;
|
|
|
|
|
|
- }
|
|
|
+ function parseVertexIndex( value ) {
|
|
|
|
|
|
- function uv( u, v ) {
|
|
|
+ var index = parseInt( value );
|
|
|
|
|
|
- return new THREE.Vector2( parseFloat( u ), parseFloat( v ) );
|
|
|
+ return ( index >= 0 ? index - 1 : index + vertices.length / 3 ) * 3;
|
|
|
|
|
|
}
|
|
|
|
|
|
- function face3( a, b, c, normals ) {
|
|
|
+ function parseNormalIndex( value ) {
|
|
|
+
|
|
|
+ var index = parseInt( value );
|
|
|
|
|
|
- return new THREE.Face3( a, b, c, normals );
|
|
|
+ return ( index >= 0 ? index - 1 : index + normals.length / 3 ) * 3;
|
|
|
|
|
|
}
|
|
|
-
|
|
|
- var object = new THREE.Object3D();
|
|
|
- var geometry, material, mesh;
|
|
|
|
|
|
- function parseVertexIndex( index ) {
|
|
|
+ function parseUVIndex( value ) {
|
|
|
|
|
|
- index = parseInt( index );
|
|
|
+ var index = parseInt( value );
|
|
|
|
|
|
- return index >= 0 ? index - 1 : index + vertices.length;
|
|
|
+ return ( index >= 0 ? index - 1 : index + uvs.length / 2 ) * 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
- function parseNormalIndex( index ) {
|
|
|
-
|
|
|
- index = parseInt( index );
|
|
|
+ function addVertex( a, b, c ) {
|
|
|
|
|
|
- return index >= 0 ? index - 1 : index + normals.length;
|
|
|
+ geometry.vertices.push(
|
|
|
+ vertices[ a ], vertices[ a + 1 ], vertices[ a + 2 ],
|
|
|
+ vertices[ b ], vertices[ b + 1 ], vertices[ b + 2 ],
|
|
|
+ vertices[ c ], vertices[ c + 1 ], vertices[ c + 2 ]
|
|
|
+ );
|
|
|
|
|
|
}
|
|
|
|
|
|
- function parseUVIndex( index ) {
|
|
|
+ function addNormal( a, b, c ) {
|
|
|
+
|
|
|
+ geometry.normals.push(
|
|
|
+ normals[ a ], normals[ a + 1 ], normals[ a + 2 ],
|
|
|
+ normals[ b ], normals[ b + 1 ], normals[ b + 2 ],
|
|
|
+ normals[ c ], normals[ c + 1 ], normals[ c + 2 ]
|
|
|
+ );
|
|
|
|
|
|
- index = parseInt( index );
|
|
|
+ }
|
|
|
+
|
|
|
+ function addUV( a, b, c ) {
|
|
|
|
|
|
- return index >= 0 ? index - 1 : index + uvs.length;
|
|
|
+ geometry.uvs.push(
|
|
|
+ uvs[ a ], uvs[ a + 1 ],
|
|
|
+ uvs[ b ], uvs[ b + 1 ],
|
|
|
+ uvs[ c ], uvs[ c + 1 ]
|
|
|
+ );
|
|
|
|
|
|
}
|
|
|
-
|
|
|
- function add_face( a, b, c, normals_inds ) {
|
|
|
|
|
|
- if ( normals_inds === undefined ) {
|
|
|
+ function addFace( a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd ) {
|
|
|
+
|
|
|
+ var ia = parseVertexIndex( a );
|
|
|
+ var ib = parseVertexIndex( b );
|
|
|
+ var ic = parseVertexIndex( c );
|
|
|
|
|
|
- geometry.faces.push( face3(
|
|
|
- vertices[ parseVertexIndex( a ) ] - 1,
|
|
|
- vertices[ parseVertexIndex( b ) ] - 1,
|
|
|
- vertices[ parseVertexIndex( c ) ] - 1
|
|
|
- ) );
|
|
|
+ if ( d === undefined ) {
|
|
|
+
|
|
|
+ addVertex( ia, ib, ic );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- geometry.faces.push( face3(
|
|
|
- vertices[ parseVertexIndex( a ) ] - 1,
|
|
|
- vertices[ parseVertexIndex( b ) ] - 1,
|
|
|
- vertices[ parseVertexIndex( c ) ] - 1,
|
|
|
- [
|
|
|
- normals[ parseNormalIndex( normals_inds[ 0 ] ) ].clone(),
|
|
|
- normals[ parseNormalIndex( normals_inds[ 1 ] ) ].clone(),
|
|
|
- normals[ parseNormalIndex( normals_inds[ 2 ] ) ].clone()
|
|
|
- ]
|
|
|
- ) );
|
|
|
+ var id = parseVertexIndex( d );
|
|
|
+
|
|
|
+ addVertex( ia, ib, id );
|
|
|
+ addVertex( ib, ic, id );
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
-
|
|
|
- function add_uvs( a, b, c ) {
|
|
|
-
|
|
|
- geometry.faceVertexUvs[ 0 ].push( [
|
|
|
- uvs[ parseUVIndex( a ) ].clone(),
|
|
|
- uvs[ parseUVIndex( b ) ].clone(),
|
|
|
- uvs[ parseUVIndex( c ) ].clone()
|
|
|
- ] );
|
|
|
+ if ( ua !== undefined ) {
|
|
|
|
|
|
- }
|
|
|
-
|
|
|
- function handle_face_line(faces, uvs, normals_inds) {
|
|
|
+ var ia = parseUVIndex( ua );
|
|
|
+ var ib = parseUVIndex( ub );
|
|
|
+ var ic = parseUVIndex( uc );
|
|
|
|
|
|
- if ( faces[ 3 ] === undefined ) {
|
|
|
-
|
|
|
- add_face( faces[ 0 ], faces[ 1 ], faces[ 2 ], normals_inds );
|
|
|
-
|
|
|
- if ( uvs !== undefined && uvs.length > 0 ) {
|
|
|
+ if ( d === undefined ) {
|
|
|
+
|
|
|
+ addUV( ia, ib, ic );
|
|
|
+
|
|
|
+ } else {
|
|
|
|
|
|
- add_uvs( uvs[ 0 ], uvs[ 1 ], uvs[ 2 ] );
|
|
|
+ var id = parseUVIndex( ud );
|
|
|
+
|
|
|
+ addUV( ia, ib, id );
|
|
|
+ addUV( ib, ic, id );
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
-
|
|
|
- if ( normals_inds !== undefined && normals_inds.length > 0 ) {
|
|
|
|
|
|
- add_face( faces[ 0 ], faces[ 1 ], faces[ 3 ], [ normals_inds[ 0 ], normals_inds[ 1 ], normals_inds[ 3 ] ] );
|
|
|
- add_face( faces[ 1 ], faces[ 2 ], faces[ 3 ], [ normals_inds[ 1 ], normals_inds[ 2 ], normals_inds[ 3 ] ] );
|
|
|
+ geometry.uvs.push( 0, 0, 0, 0, 0, 0 );
|
|
|
+
|
|
|
+ if ( d !== undefined ) {
|
|
|
+ geometry.uvs.push( 0, 0, 0, 0, 0, 0 );
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( na !== undefined ) {
|
|
|
+
|
|
|
+ var ia = parseNormalIndex( na );
|
|
|
+ var ib = parseNormalIndex( nb );
|
|
|
+ var ic = parseNormalIndex( nc );
|
|
|
+
|
|
|
+ if ( d === undefined ) {
|
|
|
+
|
|
|
+ addNormal( ia, ib, ic );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- add_face( faces[ 0 ], faces[ 1 ], faces[ 3 ] );
|
|
|
- add_face( faces[ 1 ], faces[ 2 ], faces[ 3 ] );
|
|
|
+ var id = parseNormalIndex( nd );
|
|
|
+
|
|
|
+ addNormal( ia, ib, id );
|
|
|
+ addNormal( ib, ic, id );
|
|
|
|
|
|
}
|
|
|
-
|
|
|
- if ( uvs !== undefined && uvs.length > 0 ) {
|
|
|
|
|
|
- add_uvs( uvs[ 0 ], uvs[ 1 ], uvs[ 3 ] );
|
|
|
- add_uvs( uvs[ 1 ], uvs[ 2 ], uvs[ 3 ] );
|
|
|
+ } else {
|
|
|
+
|
|
|
+ geometry.normals.push( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
|
|
|
|
|
|
+ if ( d !== undefined) {
|
|
|
+ geometry.normals.push( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
|
|
|
}
|
|
|
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
|
|
|
// create mesh if no objects in text
|
|
|
|
|
|
if ( /^o /gm.test( text ) === false ) {
|
|
|
|
|
|
- geometry = new THREE.Geometry();
|
|
|
- material = new THREE.MeshLambertMaterial();
|
|
|
- mesh = new THREE.Mesh( geometry, material );
|
|
|
- object.add( mesh );
|
|
|
+ geometry = {
|
|
|
+ vertices: [],
|
|
|
+ normals: [],
|
|
|
+ uvs: []
|
|
|
+ };
|
|
|
+
|
|
|
+ material = {
|
|
|
+ name: ''
|
|
|
+ };
|
|
|
+
|
|
|
+ object = {
|
|
|
+ name: '',
|
|
|
+ geometry: geometry,
|
|
|
+ material: material
|
|
|
+ };
|
|
|
+
|
|
|
+ objects.push( object );
|
|
|
|
|
|
}
|
|
|
|
|
@@ -190,9 +222,7 @@ THREE.OBJLoader.prototype = {
|
|
|
|
|
|
var face_pattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?/
|
|
|
|
|
|
- // fixes
|
|
|
-
|
|
|
- text = text.replace( /\\\r?\n/g, '' ); // handles line continuations \
|
|
|
+ //
|
|
|
|
|
|
var lines = text.split( '\n' );
|
|
|
|
|
@@ -211,12 +241,10 @@ THREE.OBJLoader.prototype = {
|
|
|
|
|
|
// ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
|
|
|
|
|
|
- vertices.push(
|
|
|
- geometry.vertices.push(
|
|
|
- vector(
|
|
|
- result[ 1 ], result[ 2 ], result[ 3 ]
|
|
|
- )
|
|
|
- )
|
|
|
+ vertices.push(
|
|
|
+ parseFloat( result[ 1 ] ),
|
|
|
+ parseFloat( result[ 2 ] ),
|
|
|
+ parseFloat( result[ 3 ] )
|
|
|
);
|
|
|
|
|
|
} else if ( ( result = normal_pattern.exec( line ) ) !== null ) {
|
|
@@ -224,9 +252,9 @@ THREE.OBJLoader.prototype = {
|
|
|
// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
|
|
|
|
|
|
normals.push(
|
|
|
- vector(
|
|
|
- result[ 1 ], result[ 2 ], result[ 3 ]
|
|
|
- )
|
|
|
+ parseFloat( result[ 1 ] ),
|
|
|
+ parseFloat( result[ 2 ] ),
|
|
|
+ parseFloat( result[ 3 ] )
|
|
|
);
|
|
|
|
|
|
} else if ( ( result = uv_pattern.exec( line ) ) !== null ) {
|
|
@@ -234,56 +262,66 @@ THREE.OBJLoader.prototype = {
|
|
|
// ["vt 0.1 0.2", "0.1", "0.2"]
|
|
|
|
|
|
uvs.push(
|
|
|
- uv(
|
|
|
- result[ 1 ], result[ 2 ]
|
|
|
- )
|
|
|
+ parseFloat( result[ 1 ] ),
|
|
|
+ parseFloat( result[ 2 ] )
|
|
|
);
|
|
|
|
|
|
} else if ( ( result = face_pattern1.exec( line ) ) !== null ) {
|
|
|
|
|
|
// ["f 1 2 3", "1", "2", "3", undefined]
|
|
|
|
|
|
- handle_face_line(
|
|
|
- [ result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ] ]
|
|
|
+ addFace(
|
|
|
+ result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ]
|
|
|
);
|
|
|
|
|
|
} else if ( ( result = face_pattern2.exec( line ) ) !== null ) {
|
|
|
|
|
|
// ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3", undefined, undefined, undefined]
|
|
|
|
|
|
- handle_face_line(
|
|
|
- [ result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ] ], //faces
|
|
|
- [ result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ] ] //uv
|
|
|
+ addFace(
|
|
|
+ result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ],
|
|
|
+ result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]
|
|
|
);
|
|
|
|
|
|
} else if ( ( result = face_pattern3.exec( line ) ) !== null ) {
|
|
|
|
|
|
// ["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", undefined, undefined, undefined, undefined]
|
|
|
|
|
|
- handle_face_line(
|
|
|
- [ result[ 2 ], result[ 6 ], result[ 10 ], result[ 14 ] ], //faces
|
|
|
- [ result[ 3 ], result[ 7 ], result[ 11 ], result[ 15 ] ], //uv
|
|
|
- [ result[ 4 ], result[ 8 ], result[ 12 ], result[ 16 ] ] //normal
|
|
|
+ addFace(
|
|
|
+ result[ 2 ], result[ 6 ], result[ 10 ], result[ 14 ],
|
|
|
+ result[ 3 ], result[ 7 ], result[ 11 ], result[ 15 ],
|
|
|
+ result[ 4 ], result[ 8 ], result[ 12 ], result[ 16 ]
|
|
|
);
|
|
|
|
|
|
} else if ( ( result = face_pattern4.exec( line ) ) !== null ) {
|
|
|
|
|
|
// ["f 1//1 2//2 3//3", " 1//1", "1", "1", " 2//2", "2", "2", " 3//3", "3", "3", undefined, undefined, undefined]
|
|
|
|
|
|
- handle_face_line(
|
|
|
- [ result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ] ], //faces
|
|
|
- [ ], //uv
|
|
|
- [ result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ] ] //normal
|
|
|
+ addFace(
|
|
|
+ result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ],
|
|
|
+ undefined, undefined, undefined, undefined,
|
|
|
+ result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]
|
|
|
);
|
|
|
|
|
|
} else if ( /^o /.test( line ) ) {
|
|
|
|
|
|
- geometry = new THREE.Geometry();
|
|
|
- material = new THREE.MeshLambertMaterial();
|
|
|
+ geometry = {
|
|
|
+ vertices: [],
|
|
|
+ normals: [],
|
|
|
+ uvs: []
|
|
|
+ };
|
|
|
|
|
|
- mesh = new THREE.Mesh( geometry, material );
|
|
|
- mesh.name = line.substring( 2 ).trim();
|
|
|
- object.add( mesh );
|
|
|
+ material = {
|
|
|
+ name: ''
|
|
|
+ };
|
|
|
+
|
|
|
+ object = {
|
|
|
+ name: line.substring( 2 ).trim(),
|
|
|
+ geometry: geometry,
|
|
|
+ material: material
|
|
|
+ };
|
|
|
+
|
|
|
+ objects.push( object )
|
|
|
|
|
|
} else if ( /^g /.test( line ) ) {
|
|
|
|
|
@@ -311,19 +349,31 @@ THREE.OBJLoader.prototype = {
|
|
|
|
|
|
}
|
|
|
|
|
|
- var children = object.children;
|
|
|
+ var container = new THREE.Object3D();
|
|
|
+
|
|
|
+ for ( var i = 0, l = objects.length; i < l; i ++ ) {
|
|
|
|
|
|
- for ( var i = 0, l = children.length; i < l; i ++ ) {
|
|
|
+ var object = objects[ i ];
|
|
|
|
|
|
- var geometry = children[ i ].geometry;
|
|
|
+ var geometry = new THREE.BufferGeometry();
|
|
|
+ geometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( object.geometry.vertices ), 3 ) );
|
|
|
+ geometry.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( object.geometry.normals ), 3 ) );
|
|
|
+ geometry.addAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( object.geometry.uvs ), 2 ) );
|
|
|
|
|
|
- geometry.computeFaceNormals();
|
|
|
- geometry.computeBoundingSphere();
|
|
|
+ var material = new THREE.MeshLambertMaterial();
|
|
|
+ material.name = object.material.name;
|
|
|
+
|
|
|
+ var mesh = new THREE.Mesh( geometry, material );
|
|
|
+ mesh.name = object.name;
|
|
|
+
|
|
|
+ container.add( mesh );
|
|
|
|
|
|
}
|
|
|
-
|
|
|
- return object;
|
|
|
+
|
|
|
+ console.timeEnd( 'OBJLoader' );
|
|
|
+
|
|
|
+ return container;
|
|
|
|
|
|
}
|
|
|
|
|
|
-};
|
|
|
+};
|