|
@@ -29,7 +29,7 @@ THREE.ColladaLoader.prototype = {
|
|
options: {
|
|
options: {
|
|
|
|
|
|
set convertUpAxis ( value ) {
|
|
set convertUpAxis ( value ) {
|
|
- console.log( 'ColladaLoder2: TODO' );
|
|
|
|
|
|
+ console.log( 'ColladaLoder.options.convertUpAxis: TODO' );
|
|
}
|
|
}
|
|
|
|
|
|
},
|
|
},
|
|
@@ -68,129 +68,387 @@ THREE.ColladaLoader.prototype = {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- function parseGeometries( xml ) {
|
|
|
|
|
|
+ function parseId( text ) {
|
|
|
|
|
|
- xml = xml.getElementsByTagName( 'geometry' );
|
|
|
|
|
|
+ return text.substring( 1 );
|
|
|
|
|
|
- var geometries = [];
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // cameras
|
|
|
|
+
|
|
|
|
+ function parseCamerasLibrary( xml ) {
|
|
|
|
+
|
|
|
|
+ var library = {};
|
|
|
|
|
|
- for ( var i = 0; i < xml.length; i ++ ) {
|
|
|
|
|
|
+ var cameras = xml.getElementsByTagName( 'library_cameras' )[ 0 ];
|
|
|
|
|
|
- geometries.push( parseGeometry( xml[ i ].getElementsByTagName( 'mesh' )[ 0 ] ) );
|
|
|
|
|
|
+ if ( cameras !== undefined ) {
|
|
|
|
+
|
|
|
|
+ var elements = cameras.getElementsByTagName( 'camera' );
|
|
|
|
+
|
|
|
|
+ for ( var i = 0; i < elements.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ var element = elements[ i ];
|
|
|
|
+ library[ element.getAttribute( 'id' ) ] = parseCamera( element );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- return geometries;
|
|
|
|
|
|
+ return library;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- function parseGeometry( xml ) {
|
|
|
|
|
|
+ function parseCamera( xml ) {
|
|
|
|
|
|
- var geometry = new THREE.BufferGeometry();
|
|
|
|
|
|
+ console.log( 'ColladaLoader.parseCamera: TODO')
|
|
|
|
+
|
|
|
|
+ var camera = new THREE.PerspectiveCamera();
|
|
|
|
+ camera.name = xml.getAttribute( 'name' );
|
|
|
|
+ return camera;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // geometries
|
|
|
|
+
|
|
|
|
+ function parseGeometriesLibrary( xml ) {
|
|
|
|
|
|
- // sources
|
|
|
|
|
|
+ var library = {};
|
|
|
|
|
|
- var sources = {};
|
|
|
|
- var sourceNodes = xml.getElementsByTagName( 'source' );
|
|
|
|
|
|
+ var geometries = xml.getElementsByTagName( 'library_geometries' )[ 0 ];
|
|
|
|
+ var elements = geometries.getElementsByTagName( 'geometry' );
|
|
|
|
|
|
- for ( var i = 0; i < sourceNodes.length; i ++ ) {
|
|
|
|
|
|
+ for ( var i = 0; i < elements.length; i ++ ) {
|
|
|
|
|
|
- var sourceNode = sourceNodes[ i ];
|
|
|
|
- var array = parseFloats( sourceNode.getElementsByTagName( 'float_array' )[ 0 ].textContent );
|
|
|
|
- sources[ sourceNode.getAttribute( 'id' ) ] = array;
|
|
|
|
|
|
+ var element = elements[ i ];
|
|
|
|
+ var mesh = parseMesh( element.getElementsByTagName( 'mesh' )[ 0 ] );
|
|
|
|
+
|
|
|
|
+ library[ element.getAttribute( 'id' ) ] = createGeometry( mesh );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- // vertices
|
|
|
|
|
|
+ return library;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function parseMesh( xml ) {
|
|
|
|
+
|
|
|
|
+ var mesh = {
|
|
|
|
+ sources: {}
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ for ( var i = 0; i < xml.childNodes.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ var child = xml.childNodes[ i ];
|
|
|
|
+
|
|
|
|
+ if ( child.nodeType !== 1 ) continue;
|
|
|
|
|
|
- var verticesNode = xml.getElementsByTagName( 'vertices' )[ 0 ];
|
|
|
|
- sources[ verticesNode.getAttribute( 'id' ) ] = sources[ verticesNode.getElementsByTagName( 'input' )[ 0 ].getAttribute( 'source' ).substring( 1 ) ];
|
|
|
|
|
|
+ switch ( child.nodeName ) {
|
|
|
|
|
|
- // triangles
|
|
|
|
|
|
+ case 'source':
|
|
|
|
+ mesh.sources[ child.getAttribute( 'id' ) ] = parseFloats( child.getElementsByTagName( 'float_array' )[ 0 ].textContent );
|
|
|
|
+ break;
|
|
|
|
|
|
- var triangleNodes = xml.getElementsByTagName( 'triangles' );
|
|
|
|
|
|
+ case 'vertices':
|
|
|
|
+ mesh.sources[ child.getAttribute( 'id' ) ] = mesh.sources[ parseId( child.getElementsByTagName( 'input' )[ 0 ].getAttribute( 'source' ) ) ];
|
|
|
|
+ break;
|
|
|
|
|
|
- if ( triangleNodes === null ) return geometry;
|
|
|
|
|
|
+ case 'polylist':
|
|
|
|
+ case 'triangles':
|
|
|
|
+ mesh.primitive = parsePrimitive( child );
|
|
|
|
+ break;
|
|
|
|
|
|
- for ( var i = 0; i < triangleNodes.length; i ++ ) {
|
|
|
|
|
|
+ default:
|
|
|
|
+ console.log( child );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return mesh;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
- var triangleNode = triangleNodes[ i ];
|
|
|
|
|
|
+ function parsePrimitive( xml ) {
|
|
|
|
|
|
- // indices
|
|
|
|
|
|
+ var primitive = {
|
|
|
|
+ inputs: {},
|
|
|
|
+ stride: 0
|
|
|
|
+ };
|
|
|
|
|
|
- var indices = parseInts( triangleNode.getElementsByTagName( 'p' )[ 0 ].textContent );
|
|
|
|
|
|
+ for ( var i = 0; i < xml.childNodes.length; i ++ ) {
|
|
|
|
|
|
- // inputs
|
|
|
|
|
|
+ var child = xml.childNodes[ i ];
|
|
|
|
|
|
- var inputNodes = triangleNode.getElementsByTagName( 'input' );
|
|
|
|
|
|
+ if ( child.nodeType !== 1 ) continue;
|
|
|
|
|
|
- var maxOffset = 0;
|
|
|
|
|
|
+ switch ( child.nodeName ) {
|
|
|
|
|
|
- for ( var j = 0; j < inputNodes.length; j ++ ) {
|
|
|
|
|
|
+ case 'input':
|
|
|
|
+ var id = parseId( child.getAttribute( 'source' ) );
|
|
|
|
+ var semantic = child.getAttribute( 'semantic' );
|
|
|
|
+ var offset = parseInt( child.getAttribute( 'offset' ) );
|
|
|
|
+ primitive.inputs[ semantic ] = { id: id, offset: offset };
|
|
|
|
+ primitive.stride = Math.max( primitive.stride, offset + 1 );
|
|
|
|
+ break;
|
|
|
|
|
|
- var inputNode = inputNodes[ j ];
|
|
|
|
- maxOffset = Math.max( maxOffset, parseInt( inputNode.getAttribute( 'offset' ) ) + 1 );
|
|
|
|
|
|
+ case 'vcount':
|
|
|
|
+ primitive.vcount = parseInts( child.textContent );
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'p':
|
|
|
|
+ primitive.p = parseInts( child.textContent );
|
|
|
|
+ break;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- for ( var j = 0; j < inputNodes.length; j ++ ) {
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return primitive;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function createGeometry( mesh ) {
|
|
|
|
+
|
|
|
|
+ var sources = mesh.sources;
|
|
|
|
+ var primitive = mesh.primitive;
|
|
|
|
+
|
|
|
|
+ var inputs = primitive.inputs;
|
|
|
|
+ var stride = primitive.stride;
|
|
|
|
+ var vcount = primitive.vcount;
|
|
|
|
+
|
|
|
|
+ var vcount = primitive.vcount;
|
|
|
|
+ var indices = primitive.p;
|
|
|
|
+
|
|
|
|
+ var geometry = new THREE.BufferGeometry();
|
|
|
|
+
|
|
|
|
+ for ( var name in inputs ) {
|
|
|
|
+
|
|
|
|
+ var input = inputs[ name ];
|
|
|
|
+
|
|
|
|
+ var source = sources[ input.id ];
|
|
|
|
+ var offset = input.offset;
|
|
|
|
+
|
|
|
|
+ var array = [];
|
|
|
|
+
|
|
|
|
+ function pushVector( i ) {
|
|
|
|
+
|
|
|
|
+ var index = indices[ i + offset ] * 3;
|
|
|
|
+ array.push( source[ index + 0 ], source[ index + 1 ], source[ index + 2 ] );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( primitive.vcount !== undefined ) {
|
|
|
|
+
|
|
|
|
+ var index = 0;
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, l = vcount.length; i < l; i ++ ) {
|
|
|
|
+
|
|
|
|
+ var count = vcount[ i ];
|
|
|
|
+
|
|
|
|
+ if ( count === 4 ) {
|
|
|
|
+
|
|
|
|
+ var a = index + stride * 0;
|
|
|
|
+ var b = index + stride * 1;
|
|
|
|
+ var c = index + stride * 2;
|
|
|
|
+ var d = index + stride * 3;
|
|
|
|
+
|
|
|
|
+ pushVector( a );
|
|
|
|
+ pushVector( b );
|
|
|
|
+ pushVector( d );
|
|
|
|
+
|
|
|
|
+ pushVector( b );
|
|
|
|
+ pushVector( c );
|
|
|
|
+ pushVector( d );
|
|
|
|
+
|
|
|
|
+ } else if ( count === 3 ) {
|
|
|
|
+
|
|
|
|
+ var a = index + stride * 0;
|
|
|
|
+ var b = index + stride * 1;
|
|
|
|
+ var c = index + stride * 2;
|
|
|
|
|
|
- var inputNode = inputNodes[ j ];
|
|
|
|
|
|
+ pushVector( a );
|
|
|
|
+ pushVector( b );
|
|
|
|
+ pushVector( c );
|
|
|
|
|
|
- var source = sources[ inputNode.getAttribute( 'source' ).substring( 1 ) ];
|
|
|
|
- var offset = parseInt( inputNode.getAttribute( 'offset' ) );
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- var array = [];
|
|
|
|
|
|
+ console.log( 'ColladaLoader.createGeometry:', count, 'not supported.' );
|
|
|
|
|
|
- for ( var k = offset; k < indices.length; k += maxOffset ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var index = indices[ k ] * 3;
|
|
|
|
- array.push( source[ index + 0 ], source[ index + 1 ], source[ index + 2 ] );
|
|
|
|
|
|
+ index += stride * count;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- switch ( inputNode.getAttribute( 'semantic' ) ) {
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- case 'VERTEX':
|
|
|
|
- geometry.addAttribute( 'position', new THREE.Float32Attribute( array, 3 ) );
|
|
|
|
- break;
|
|
|
|
|
|
+ for ( var i = 0, l = indices.length; i < l; i += stride ) {
|
|
|
|
|
|
- case 'NORMAL':
|
|
|
|
- geometry.addAttribute( 'normal', new THREE.Float32Attribute( array, 3 ) );
|
|
|
|
- break;
|
|
|
|
|
|
+ pushVector( i );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ switch ( name ) {
|
|
|
|
+
|
|
|
|
+ case 'VERTEX':
|
|
|
|
+ geometry.addAttribute( 'position', new THREE.Float32Attribute( array, 3 ) );
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'NORMAL':
|
|
|
|
+ geometry.addAttribute( 'normal', new THREE.Float32Attribute( array, 3 ) );
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
return geometry;
|
|
return geometry;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- console.time( 'ColladaLoader2' );
|
|
|
|
|
|
+ // nodes
|
|
|
|
|
|
- var xml = new DOMParser().parseFromString( text, 'text/xml' );
|
|
|
|
|
|
+ function parseNodesLibrary( xml ) {
|
|
|
|
+
|
|
|
|
+ var library = {};
|
|
|
|
+ return library;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function parseNode( xml ) {
|
|
|
|
+
|
|
|
|
+ var group = new THREE.Group();
|
|
|
|
+ group.name = xml.getAttribute( 'name' );
|
|
|
|
+
|
|
|
|
+ var matrix = new THREE.Matrix4();
|
|
|
|
+
|
|
|
|
+ for ( var i = 0; i < xml.childNodes.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ var child = xml.childNodes[ i ];
|
|
|
|
|
|
- var geometries = xml.getElementsByTagName( 'library_geometries' )[ 0 ];
|
|
|
|
- // var materials = xml.getElementsByTagName( 'library_materials' )[ 0 ];
|
|
|
|
- // var images = xml.getElementsByTagName( 'library_images' )[ 0 ];
|
|
|
|
- // var effects = xml.getElementsByTagName( 'library_effects' )[ 0 ];
|
|
|
|
|
|
+ if ( child.nodeType !== 1 ) continue;
|
|
|
|
|
|
- var scene = new THREE.Scene();
|
|
|
|
|
|
+ switch ( child.nodeName ) {
|
|
|
|
|
|
- var geometries = parseGeometries( geometries );
|
|
|
|
- var material = new THREE.MeshPhongMaterial();
|
|
|
|
|
|
+ case 'node':
|
|
|
|
+ group.add( parseNode( child ) );
|
|
|
|
+ break;
|
|
|
|
|
|
- for ( var i = 0; i < geometries.length; i ++ ) {
|
|
|
|
|
|
+ case 'instance_camera':
|
|
|
|
+ var camera = camerasLibrary[ parseId( child.getAttribute( 'url' ) ) ];
|
|
|
|
+ group.add( camera );
|
|
|
|
+ break;
|
|
|
|
|
|
- scene.add( new THREE.Mesh( geometries[ i ], material ) );
|
|
|
|
|
|
+ case 'instance_geometry':
|
|
|
|
+ var geometry = geometriesLibrary[ parseId( child.getAttribute( 'url' ) ) ];
|
|
|
|
+ var material = new THREE.MeshPhongMaterial();
|
|
|
|
+ var mesh = new THREE.Mesh( geometry, material );
|
|
|
|
+ group.add( mesh );
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'matrix':
|
|
|
|
+ matrix.multiply( new THREE.Matrix4().fromArray( parseFloats( child.textContent ) ) );
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'translate':
|
|
|
|
+ var vector = new THREE.Vector3().fromArray( parseFloats( child.textContent ) );
|
|
|
|
+ matrix.multiply( new THREE.Matrix4().makeTranslation( vector.x, vector.y, vector.z ) );
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'rotate':
|
|
|
|
+ var array = parseFloats( child.textContent );
|
|
|
|
+ var axis = new THREE.Vector3().fromArray( array );
|
|
|
|
+ var angle = THREE.Math.degToRad( array[ 3 ] );
|
|
|
|
+ matrix.multiply( new THREE.Matrix4().makeRotationAxis( axis, angle ) );
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'scale':
|
|
|
|
+ var vector = new THREE.Vector3().fromArray( parseFloats( child.textContent ) );
|
|
|
|
+ matrix.scale( vector );
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case 'extra':
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ console.log( child );
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ matrix.decompose( group.position, group.quaternion, group.scale );
|
|
|
|
+
|
|
|
|
+ return group;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // visual scenes
|
|
|
|
+
|
|
|
|
+ function parseVisualScenesLibrary( xml ) {
|
|
|
|
+
|
|
|
|
+ var library = {};
|
|
|
|
+
|
|
|
|
+ var visualScenes = xml.getElementsByTagName( 'library_visual_scenes' )[ 0 ];
|
|
|
|
+ var elements = visualScenes.getElementsByTagName( 'visual_scene' );
|
|
|
|
+
|
|
|
|
+ for ( var i = 0; i < elements.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ var element = elements[ i ];
|
|
|
|
+ library[ element.getAttribute( 'id' ) ] = parseVisualScene( element );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return library;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function parseVisualScene( xml ) {
|
|
|
|
+
|
|
|
|
+ var group = new THREE.Group();
|
|
|
|
+ group.name = xml.getAttribute( 'name' );
|
|
|
|
+
|
|
|
|
+ var elements = xml.getElementsByTagName( 'node' );
|
|
|
|
+
|
|
|
|
+ for ( var i = 0; i < elements.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ var element = elements[ i ];
|
|
|
|
+ group.add( parseNode( element ) );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return group;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // scenes
|
|
|
|
+
|
|
|
|
+ function parseScene( xml ) {
|
|
|
|
+
|
|
|
|
+ var scene = xml.getElementsByTagName( 'scene' )[ 0 ];
|
|
|
|
+ var instance = scene.getElementsByTagName( 'instance_visual_scene' )[ 0 ];
|
|
|
|
+ return visualScenesLibrary[ parseId( instance.getAttribute( 'url' ) ) ];
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ console.time( 'ColladaLoader2' );
|
|
|
|
+
|
|
|
|
+ var xml = new DOMParser().parseFromString( text, 'text/xml' );
|
|
|
|
+
|
|
|
|
+ var camerasLibrary = parseCamerasLibrary( xml );
|
|
|
|
+ var geometriesLibrary = parseGeometriesLibrary( xml );
|
|
|
|
+ var nodesLibrary = parseNodesLibrary( xml );
|
|
|
|
+ var visualScenesLibrary = parseVisualScenesLibrary( xml );
|
|
|
|
+ var scene = parseScene( xml );
|
|
|
|
+
|
|
console.timeEnd( 'ColladaLoader2' );
|
|
console.timeEnd( 'ColladaLoader2' );
|
|
|
|
|
|
|
|
+ // console.log( scene );
|
|
|
|
+
|
|
return {
|
|
return {
|
|
animations: [],
|
|
animations: [],
|
|
kinematics: { joints: [] },
|
|
kinematics: { joints: [] },
|