/** * @author mrdoob / http://mrdoob.com/ * @author alteredq / http://alteredqualia.com/ */ THREE.JSONLoader = function ( showStatus ) { THREE.Loader.call( this, showStatus ); }; THREE.JSONLoader.prototype = new THREE.Loader(); THREE.JSONLoader.prototype.constructor = THREE.JSONLoader; THREE.JSONLoader.prototype.supr = THREE.Loader.prototype; /** * Load models generated by slim OBJ converter with ASCII option (converter_obj_three_slim.py -t ascii) * - parameters * - model (required) * - callback (required) * - texture_path (optional: if not specified, textures will be assumed to be in the same folder as JS model file) */ THREE.JSONLoader.prototype.load = function ( parameters ) { var scope = this, url = parameters.model, callback = parameters.callback, texture_path = parameters.texture_path ? parameters.texture_path : this.extractUrlbase( url ), worker = new Worker( url ); worker.onmessage = function ( event ) { scope.createModel( event.data, callback, texture_path ); scope.onLoadComplete(); }; this.onLoadStart(); worker.postMessage( new Date().getTime() ); }; THREE.JSONLoader.prototype.createModel = function ( json, callback, texture_path ) { var scope = this, geometry = new THREE.Geometry(), scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0; this.init_materials( geometry, json.materials, texture_path ); parseModel( scale ); parseSkin(); parseMorphing( scale ); parseEdges(); geometry.computeCentroids(); geometry.computeFaceNormals(); if ( this.hasNormals( geometry ) ) geometry.computeTangents(); // geometry.computeEdgeFaces(); function parseModel( scale ) { if ( json.version === undefined || json.version != 2 ) { console.error( 'Deprecated file format.' ); return; } function isBitSet( value, position ) { return value & ( 1 << position ); }; var i, j, fi, offset, zLength, nVertices, colorIndex, normalIndex, uvIndex, materialIndex, type, isQuad, hasMaterial, hasFaceUv, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor, vertex, face, color, normal, uvLayer, uvs, u, v, faces = json.faces, vertices = json.vertices, normals = json.normals, colors = json.colors, nUvLayers = 0; // disregard empty arrays for ( i = 0; i < json.uvs.length; i++ ) { if ( json.uvs[ i ].length ) nUvLayers ++; } for ( i = 0; i < nUvLayers; i++ ) { geometry.faceUvs[ i ] = []; geometry.faceVertexUvs[ i ] = []; } offset = 0; zLength = vertices.length; while ( offset < zLength ) { vertex = new THREE.Vertex(); vertex.position.x = vertices[ offset ++ ] * scale; vertex.position.y = vertices[ offset ++ ] * scale; vertex.position.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 ); hasFaceUv = isBitSet( type, 2 ); 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, hasFaceUv, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor); if ( isQuad ) { face = new THREE.Face4(); face.a = faces[ offset ++ ]; face.b = faces[ offset ++ ]; face.c = faces[ offset ++ ]; face.d = faces[ offset ++ ]; nVertices = 4; } else { face = new THREE.Face3(); face.a = faces[ offset ++ ]; face.b = faces[ offset ++ ]; face.c = faces[ offset ++ ]; nVertices = 3; } if ( hasMaterial ) { materialIndex = faces[ offset ++ ]; face.materials = geometry.materials[ materialIndex ]; } // to get face <=> uv index correspondence fi = geometry.faces.length; if ( hasFaceUv ) { for ( i = 0; i < nUvLayers; i++ ) { uvLayer = json.uvs[ i ]; uvIndex = faces[ offset ++ ]; u = uvLayer[ uvIndex * 2 ]; v = uvLayer[ uvIndex * 2 + 1 ]; geometry.faceUvs[ i ][ fi ] = new THREE.UV( u, v ); } } if ( hasFaceVertexUv ) { for ( i = 0; i < nUvLayers; i++ ) { uvLayer = json.uvs[ i ]; uvs = []; for ( j = 0; j < nVertices; j ++ ) { uvIndex = faces[ offset ++ ]; u = uvLayer[ uvIndex * 2 ]; v = uvLayer[ uvIndex * 2 + 1 ]; uvs[ j ] = new THREE.UV( u, v ); } geometry.faceVertexUvs[ i ][ fi ] = uvs; } } if ( hasFaceNormal ) { normalIndex = faces[ offset ++ ] * 3; normal = new THREE.Vector3(); normal.x = normals[ normalIndex ++ ]; normal.y = normals[ normalIndex ++ ]; normal.z = normals[ normalIndex ]; face.normal = normal; } if ( hasFaceVertexNormal ) { for ( i = 0; i < nVertices; i++ ) { normalIndex = faces[ offset ++ ] * 3; normal = new THREE.Vector3(); normal.x = normals[ normalIndex ++ ]; normal.y = normals[ normalIndex ++ ]; normal.z = normals[ normalIndex ]; face.vertexNormals.push( normal ); } } if ( hasFaceColor ) { colorIndex = faces[ offset ++ ]; color = new THREE.Color( colors[ colorIndex ] ); face.color = color; } if ( hasFaceVertexColor ) { for ( i = 0; i < nVertices; i++ ) { colorIndex = faces[ offset ++ ]; color = new THREE.Color( colors[ colorIndex ] ); face.vertexColors.push( color ); } } geometry.faces.push( face ); } }; function parseSkin() { var i, l, x, y, z, w, a, b, c, d; if ( json.skinWeights ) { for ( i = 0, l = json.skinWeights.length; i < l; i += 2 ) { x = json.skinWeights[ i ]; y = json.skinWeights[ i + 1 ]; z = 0; w = 0; geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) ); } } if ( json.skinIndices ) { for ( i = 0, l = json.skinIndices.length; i < l; i += 2 ) { a = json.skinIndices[ i ]; b = json.skinIndices[ i + 1 ]; c = 0; d = 0; geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) ); } } geometry.bones = json.bones; geometry.animation = json.animation; }; function parseMorphing( scale ) { if ( json.morphTargets !== undefined ) { var i, l, v, vl, x, y, z, dstVertices, srcVertices; for ( i = 0, l = json.morphTargets.length; i < l; i++ ) { geometry.morphTargets[ i ] = {}; geometry.morphTargets[ i ].name = json.morphTargets[ i ].name; geometry.morphTargets[ i ].vertices = []; dstVertices = geometry.morphTargets[ i ].vertices; srcVertices = json.morphTargets [ i ].vertices; for( v = 0, vl = srcVertices.length; v < vl; v += 3 ) { x = srcVertices[ v ] * scale; y = srcVertices[ v + 1 ] * scale; z = srcVertices[ v + 2 ] * scale; dstVertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ); } } } if ( json.morphColors !== undefined ) { var i, l, c, cl, dstColors, srcColors, color; for ( i = 0, l = json.morphColors.length; i < l; i++ ) { geometry.morphColors[ i ] = {}; geometry.morphColors[ i ].name = json.morphColors[ i ].name; geometry.morphColors[ i ].colors = []; dstColors = geometry.morphColors[ i ].colors; srcColors = json.morphColors [ i ].colors; for ( c = 0, cl = srcColors.length; c < cl; c += 3 ) { color = new THREE.Color( 0xffaa00 ); color.setRGB( srcColors[ c ], srcColors[ c + 1 ], srcColors[ c + 2 ] ); dstColors.push( color ); } } } }; function parseEdges() { if( json.edges !== undefined ) { var i, il, v1, v2; for ( i = 0; i < json.edges.length; i+= 2 ) { v1 = json.edges[ i ]; v2 = json.edges[ i + 1 ]; geometry.edges.push( new THREE.Edge( geometry.vertices[ v1 ], geometry.vertices[ v2 ], v1, v2 ) ); } } }; callback( geometry ); }