Spaces:
Running
Running
| /** | |
| * @author mrdoob / http://mrdoob.com/ | |
| * @author alteredq / http://alteredqualia.com/ | |
| */ | |
| THREE.LegacyJSONLoader = ( function () { | |
| function LegacyJSONLoader( manager ) { | |
| if ( typeof manager === 'boolean' ) { | |
| console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' ); | |
| manager = undefined; | |
| } | |
| this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; | |
| this.withCredentials = false; | |
| } | |
| Object.assign( LegacyJSONLoader.prototype, { | |
| crossOrigin: 'anonymous', | |
| load: function ( url, onLoad, onProgress, onError ) { | |
| var scope = this; | |
| var path = ( this.path === undefined ) ? THREE.LoaderUtils.extractUrlBase( url ) : this.path; | |
| var loader = new THREE.FileLoader( this.manager ); | |
| loader.setPath( this.path ); | |
| loader.setWithCredentials( this.withCredentials ); | |
| loader.load( url, function ( text ) { | |
| var json = JSON.parse( text ); | |
| var metadata = json.metadata; | |
| if ( metadata !== undefined ) { | |
| var type = metadata.type; | |
| if ( type !== undefined ) { | |
| if ( type.toLowerCase() === 'object' ) { | |
| console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' ); | |
| return; | |
| } | |
| } | |
| } | |
| var object = scope.parse( json, path ); | |
| onLoad( object.geometry, object.materials ); | |
| }, onProgress, onError ); | |
| }, | |
| setPath: function ( value ) { | |
| this.path = value; | |
| return this; | |
| }, | |
| setResourcePath: function ( value ) { | |
| this.resourcePath = value; | |
| return this; | |
| }, | |
| setCrossOrigin: function ( value ) { | |
| this.crossOrigin = value; | |
| return this; | |
| }, | |
| parse: ( function () { | |
| function parseModel( json, geometry ) { | |
| function isBitSet( value, position ) { | |
| return value & ( 1 << position ); | |
| } | |
| var i, j, fi, | |
| offset, zLength, | |
| colorIndex, normalIndex, uvIndex, materialIndex, | |
| type, | |
| isQuad, | |
| hasMaterial, | |
| hasFaceVertexUv, | |
| hasFaceNormal, hasFaceVertexNormal, | |
| hasFaceColor, hasFaceVertexColor, | |
| vertex, face, faceA, faceB, hex, normal, | |
| uvLayer, uv, u, v, | |
| faces = json.faces, | |
| vertices = json.vertices, | |
| normals = json.normals, | |
| colors = json.colors, | |
| scale = json.scale, | |
| nUvLayers = 0; | |
| if ( json.uvs !== undefined ) { | |
| // disregard empty arrays | |
| for ( i = 0; i < json.uvs.length; i ++ ) { | |
| if ( json.uvs[ i ].length ) nUvLayers ++; | |
| } | |
| for ( i = 0; i < nUvLayers; i ++ ) { | |
| geometry.faceVertexUvs[ i ] = []; | |
| } | |
| } | |
| offset = 0; | |
| zLength = vertices.length; | |
| while ( offset < zLength ) { | |
| vertex = new THREE.Vector3(); | |
| vertex.x = vertices[ offset ++ ] * scale; | |
| vertex.y = vertices[ offset ++ ] * scale; | |
| vertex.z = vertices[ offset ++ ] * scale; | |
| geometry.vertices.push( vertex ); | |
| } | |
| offset = 0; | |
| zLength = faces.length; | |
| while ( offset < zLength ) { | |
| type = faces[ offset ++ ]; | |
| isQuad = isBitSet( type, 0 ); | |
| hasMaterial = isBitSet( type, 1 ); | |
| hasFaceVertexUv = isBitSet( type, 3 ); | |
| hasFaceNormal = isBitSet( type, 4 ); | |
| hasFaceVertexNormal = isBitSet( type, 5 ); | |
| hasFaceColor = isBitSet( type, 6 ); | |
| hasFaceVertexColor = isBitSet( type, 7 ); | |
| // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor); | |
| if ( isQuad ) { | |
| faceA = new THREE.Face3(); | |
| faceA.a = faces[ offset ]; | |
| faceA.b = faces[ offset + 1 ]; | |
| faceA.c = faces[ offset + 3 ]; | |
| faceB = new THREE.Face3(); | |
| faceB.a = faces[ offset + 1 ]; | |
| faceB.b = faces[ offset + 2 ]; | |
| faceB.c = faces[ offset + 3 ]; | |
| offset += 4; | |
| if ( hasMaterial ) { | |
| materialIndex = faces[ offset ++ ]; | |
| faceA.materialIndex = materialIndex; | |
| faceB.materialIndex = materialIndex; | |
| } | |
| // to get face <=> uv index correspondence | |
| fi = geometry.faces.length; | |
| if ( hasFaceVertexUv ) { | |
| for ( i = 0; i < nUvLayers; i ++ ) { | |
| uvLayer = json.uvs[ i ]; | |
| geometry.faceVertexUvs[ i ][ fi ] = []; | |
| geometry.faceVertexUvs[ i ][ fi + 1 ] = []; | |
| for ( j = 0; j < 4; j ++ ) { | |
| uvIndex = faces[ offset ++ ]; | |
| u = uvLayer[ uvIndex * 2 ]; | |
| v = uvLayer[ uvIndex * 2 + 1 ]; | |
| uv = new THREE.Vector2( u, v ); | |
| if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv ); | |
| if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv ); | |
| } | |
| } | |
| } | |
| if ( hasFaceNormal ) { | |
| normalIndex = faces[ offset ++ ] * 3; | |
| faceA.normal.set( | |
| normals[ normalIndex ++ ], | |
| normals[ normalIndex ++ ], | |
| normals[ normalIndex ] | |
| ); | |
| faceB.normal.copy( faceA.normal ); | |
| } | |
| if ( hasFaceVertexNormal ) { | |
| for ( i = 0; i < 4; i ++ ) { | |
| normalIndex = faces[ offset ++ ] * 3; | |
| normal = new THREE.Vector3( | |
| normals[ normalIndex ++ ], | |
| normals[ normalIndex ++ ], | |
| normals[ normalIndex ] | |
| ); | |
| if ( i !== 2 ) faceA.vertexNormals.push( normal ); | |
| if ( i !== 0 ) faceB.vertexNormals.push( normal ); | |
| } | |
| } | |
| if ( hasFaceColor ) { | |
| colorIndex = faces[ offset ++ ]; | |
| hex = colors[ colorIndex ]; | |
| faceA.color.setHex( hex ); | |
| faceB.color.setHex( hex ); | |
| } | |
| if ( hasFaceVertexColor ) { | |
| for ( i = 0; i < 4; i ++ ) { | |
| colorIndex = faces[ offset ++ ]; | |
| hex = colors[ colorIndex ]; | |
| if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) ); | |
| if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) ); | |
| } | |
| } | |
| geometry.faces.push( faceA ); | |
| geometry.faces.push( faceB ); | |
| } else { | |
| face = new THREE.Face3(); | |
| face.a = faces[ offset ++ ]; | |
| face.b = faces[ offset ++ ]; | |
| face.c = faces[ offset ++ ]; | |
| if ( hasMaterial ) { | |
| materialIndex = faces[ offset ++ ]; | |
| face.materialIndex = materialIndex; | |
| } | |
| // to get face <=> uv index correspondence | |
| fi = geometry.faces.length; | |
| if ( hasFaceVertexUv ) { | |
| for ( i = 0; i < nUvLayers; i ++ ) { | |
| uvLayer = json.uvs[ i ]; | |
| geometry.faceVertexUvs[ i ][ fi ] = []; | |
| for ( j = 0; j < 3; j ++ ) { | |
| uvIndex = faces[ offset ++ ]; | |
| u = uvLayer[ uvIndex * 2 ]; | |
| v = uvLayer[ uvIndex * 2 + 1 ]; | |
| uv = new THREE.Vector2( u, v ); | |
| geometry.faceVertexUvs[ i ][ fi ].push( uv ); | |
| } | |
| } | |
| } | |
| if ( hasFaceNormal ) { | |
| normalIndex = faces[ offset ++ ] * 3; | |
| face.normal.set( | |
| normals[ normalIndex ++ ], | |
| normals[ normalIndex ++ ], | |
| normals[ normalIndex ] | |
| ); | |
| } | |
| if ( hasFaceVertexNormal ) { | |
| for ( i = 0; i < 3; i ++ ) { | |
| normalIndex = faces[ offset ++ ] * 3; | |
| normal = new THREE.Vector3( | |
| normals[ normalIndex ++ ], | |
| normals[ normalIndex ++ ], | |
| normals[ normalIndex ] | |
| ); | |
| face.vertexNormals.push( normal ); | |
| } | |
| } | |
| if ( hasFaceColor ) { | |
| colorIndex = faces[ offset ++ ]; | |
| face.color.setHex( colors[ colorIndex ] ); | |
| } | |
| if ( hasFaceVertexColor ) { | |
| for ( i = 0; i < 3; i ++ ) { | |
| colorIndex = faces[ offset ++ ]; | |
| face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) ); | |
| } | |
| } | |
| geometry.faces.push( face ); | |
| } | |
| } | |
| } | |
| function parseSkin( json, geometry ) { | |
| var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2; | |
| if ( json.skinWeights ) { | |
| for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) { | |
| var x = json.skinWeights[ i ]; | |
| var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0; | |
| var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0; | |
| var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0; | |
| geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) ); | |
| } | |
| } | |
| if ( json.skinIndices ) { | |
| for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) { | |
| var a = json.skinIndices[ i ]; | |
| var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0; | |
| var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0; | |
| var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0; | |
| geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) ); | |
| } | |
| } | |
| geometry.bones = json.bones; | |
| if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) { | |
| console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' + | |
| geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' ); | |
| } | |
| } | |
| function parseMorphing( json, geometry ) { | |
| var scale = json.scale; | |
| if ( json.morphTargets !== undefined ) { | |
| for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) { | |
| geometry.morphTargets[ i ] = {}; | |
| geometry.morphTargets[ i ].name = json.morphTargets[ i ].name; | |
| geometry.morphTargets[ i ].vertices = []; | |
| var dstVertices = geometry.morphTargets[ i ].vertices; | |
| var srcVertices = json.morphTargets[ i ].vertices; | |
| for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) { | |
| var vertex = new THREE.Vector3(); | |
| vertex.x = srcVertices[ v ] * scale; | |
| vertex.y = srcVertices[ v + 1 ] * scale; | |
| vertex.z = srcVertices[ v + 2 ] * scale; | |
| dstVertices.push( vertex ); | |
| } | |
| } | |
| } | |
| if ( json.morphColors !== undefined && json.morphColors.length > 0 ) { | |
| console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' ); | |
| var faces = geometry.faces; | |
| var morphColors = json.morphColors[ 0 ].colors; | |
| for ( var i = 0, l = faces.length; i < l; i ++ ) { | |
| faces[ i ].color.fromArray( morphColors, i * 3 ); | |
| } | |
| } | |
| } | |
| function parseAnimations( json, geometry ) { | |
| var outputAnimations = []; | |
| // parse old style Bone/Hierarchy animations | |
| var animations = []; | |
| if ( json.animation !== undefined ) { | |
| animations.push( json.animation ); | |
| } | |
| if ( json.animations !== undefined ) { | |
| if ( json.animations.length ) { | |
| animations = animations.concat( json.animations ); | |
| } else { | |
| animations.push( json.animations ); | |
| } | |
| } | |
| for ( var i = 0; i < animations.length; i ++ ) { | |
| var clip = THREE.AnimationClip.parseAnimation( animations[ i ], geometry.bones ); | |
| if ( clip ) outputAnimations.push( clip ); | |
| } | |
| // parse implicit morph animations | |
| if ( geometry.morphTargets ) { | |
| // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary. | |
| var morphAnimationClips = THREE.AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 ); | |
| outputAnimations = outputAnimations.concat( morphAnimationClips ); | |
| } | |
| if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations; | |
| } | |
| return function parse( json, path ) { | |
| if ( json.data !== undefined ) { | |
| // Geometry 4.0 spec | |
| json = json.data; | |
| } | |
| if ( json.scale !== undefined ) { | |
| json.scale = 1.0 / json.scale; | |
| } else { | |
| json.scale = 1.0; | |
| } | |
| var geometry = new THREE.Geometry(); | |
| parseModel( json, geometry ); | |
| parseSkin( json, geometry ); | |
| parseMorphing( json, geometry ); | |
| parseAnimations( json, geometry ); | |
| geometry.computeFaceNormals(); | |
| geometry.computeBoundingSphere(); | |
| if ( json.materials === undefined || json.materials.length === 0 ) { | |
| return { geometry: geometry }; | |
| } else { | |
| var materials = THREE.Loader.prototype.initMaterials( json.materials, this.resourcePath || path, this.crossOrigin ); | |
| return { geometry: geometry, materials: materials }; | |
| } | |
| }; | |
| } )() | |
| } ); | |
| return LegacyJSONLoader; | |
| } )(); | |