/* * The MIT License * Copyright © 2010-2014 three.js authors * Copyright © 2014 Digia Plc and/or its subsidiary(-ies). * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ function GLModel() { this.vertices = []; this.normals = []; this.texCoords = []; this.indices = []; } function Geometry() { this.vertices = []; this.faceVertexUvs = []; this.faces = []; } function Face3( a, b, c, normal, color, materialIndex ) { this.a = a; this.b = b; this.c = c; this.normal = normal instanceof Vector3 ? normal : new Vector3(); this.vertexNormals = normal instanceof Array ? normal : [ ]; this.color = color instanceof Array ? color : [ ]; this.vertexColors = color instanceof Array ? color : []; this.vertexTangents = []; this.materialIndex = materialIndex !== undefined ? materialIndex : 0; this.centroid = new Vector3() }; function Vector2( x, y ) { this.x = x || 0; this.y = y || 0; }; function Vector3( x, y, z ) { this.x = x || 0; this.y = y || 0; this.z = z || 0; }; Vector3.prototype = { constructor: Vector3, set: function ( x, y, z ) { this.x = x; this.y = y; this.z = z; return this; }, copy: function ( v ) { this.x = v.x; this.y = v.y; this.z = v.z; return this; } }; Face3.prototype = { constructor: Face3, clone: function () { var face = new Face3( this.a, this.b, this.c ); face.normal.copy( this.normal ); face.color.copy( this.color ); face.centroid.copy( this.centroid ); face.materialIndex = this.materialIndex; var i, il; for ( i = 0, il = this.vertexNormals.length; i < il; i ++ ) face.vertexNormals[ i ] = this.vertexNormals[ i ].clone(); for ( i = 0, il = this.vertexColors.length; i < il; i ++ ) face.vertexColors[ i ] = this.vertexColors[ i ].clone(); for ( i = 0, il = this.vertexTangents.length; i < il; i ++ ) face.vertexTangents[ i ] = this.vertexTangents[ i ].clone(); return face; } }; function parseJSON3DModel( json, texturePath ) { var formatVersion = json.metadata.formatVersion; if (formatVersion < 4.0 ) { var i, j; var geometry = new Geometry(); var scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0; parseModel( json, geometry, scale ); // Translate to model we can use from GL var glModel = new GLModel(); for (i = 0; i < geometry.vertices.length; i++) { glModel.vertices.push(geometry.vertices[i].x); glModel.vertices.push(geometry.vertices[i].y); glModel.vertices.push(geometry.vertices[i].z); } glModel.texCoords[0] = []; for (var faceIdx = 0; faceIdx < geometry.faces.length; faceIdx++) { var face = geometry.faces[faceIdx]; // Array indices glModel.indices.push(face.a); glModel.indices.push(face.b); glModel.indices.push(face.c); // Materials // face.materialIndex // Only parse first layer of UVs for this face for(var uvLayer = 0; uvLayer < geometry.faceVertexUvs.length; uvLayer++) { var faceUVs = geometry.faceVertexUvs[uvLayer][faceIdx]; var idxUVA = face.a * 2; var idxUVB = face.b * 2; var idxUVC = face.c * 2; glModel.texCoords[uvLayer][idxUVA++] = faceUVs[0].x; glModel.texCoords[uvLayer][idxUVA ] = faceUVs[0].y; glModel.texCoords[uvLayer][idxUVB++] = faceUVs[1].x; glModel.texCoords[uvLayer][idxUVB ] = faceUVs[1].y; glModel.texCoords[uvLayer][idxUVC++] = faceUVs[2].x; glModel.texCoords[uvLayer][idxUVC ] = faceUVs[2].y; } // Normal if (face.vertexNormals !== undefined) { // Per vertex normals var idxA = face.a * 3; var idxB = face.b * 3; var idxC = face.c * 3; var vrtNormals = face.vertexNormals; glModel.normals[idxA++] = vrtNormals[0].x; glModel.normals[idxA++] = vrtNormals[0].y; glModel.normals[idxA ] = vrtNormals[0].z; glModel.normals[idxB++] = vrtNormals[1].x; glModel.normals[idxB++] = vrtNormals[1].y; glModel.normals[idxB ] = vrtNormals[1].z; glModel.normals[idxC++] = vrtNormals[2].x; glModel.normals[idxC++] = vrtNormals[2].y; glModel.normals[idxC ] = vrtNormals[2].z; } else if (face.normal !== undefined) { // Per face normal glModel.normals[idxA++] = face.normal.x; glModel.normals[idxA++] = face.normal.y; glModel.normals[idxA ] = face.normal.z; glModel.normals[idxB++] = face.normal.x; glModel.normals[idxB++] = face.normal.y; glModel.normals[idxB ] = face.normal.z; glModel.normals[idxC++] = face.normal.x; glModel.normals[idxC++] = face.normal.y; glModel.normals[idxC ] = face.normal.z; } } } return glModel; }; function parseModel( json, geometry, scale ) { 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, color, hex, normal, uvLayer, uv, u, v, faces = json.faces, vertices = json.vertices, normals = json.normals, colors = json.colors, nUvLayers = 0; if ( json.uvs !== undefined ) { // disregard empty arrays for ( i = 0; i < json.uvs.length; i++ ) { if ( json.uvs[ i ].length > 0 ) nUvLayers ++; } for ( i = 0; i < nUvLayers; i++ ) { geometry.faceVertexUvs[ i ] = []; } } offset = 0; zLength = vertices.length; while ( offset < zLength ) { vertex = new 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 Face3(); faceA.a = faces[ offset ]; faceA.b = faces[ offset + 1 ]; faceA.c = faces[ offset + 3 ]; faceB = new 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 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 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 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 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 Vector3( normals[ normalIndex ++ ], normals[ normalIndex ++ ], normals[ normalIndex ] ); face.vertexNormals.push( normal ); } } if ( hasFaceColor ) { // colorIndex = faces[ offset ]; offset++; // face.color.setHex( colors[ colorIndex ] ); } if ( hasFaceVertexColor ) { for ( i = 0; i < 3; i++ ) { // colorIndex = faces[offset]; offset++; // face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) ); } } geometry.faces.push( face ); } } };