diff --git a/examples/js/loaders/VRMLLoader.js b/examples/js/loaders/VRMLLoader.js index 7a3741ac5f6bc6fe22eb71857f48c648423e9518..3e9f3d558809f3167e14fda591df2e27f066c5eb 100644 --- a/examples/js/loaders/VRMLLoader.js +++ b/examples/js/loaders/VRMLLoader.js @@ -912,91 +912,144 @@ THREE.VRMLLoader.prototype = { } - var skip = 0; - // some shapes only have vertices for use in other shapes if ( data.coordIndex ) { + function triangulateIndexArray( indexArray ) { + + var triangulatedIndexArray = []; + var ccw = data.ccw === undefined ? true : data.ccw; // ccw is true by default + var skip = 0; + + for ( i = 0, il = indexArray.length; i < il; i ++ ) { + + var indexedFace = data.coordIndex[ i ]; + + // VRML support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here + + skip = 0; + + while ( indexedFace.length >= 3 && skip < ( indexedFace.length - 2 ) ) { + + var i1 = indexedFace[ 0 ]; + var i2 = indexedFace[ skip + ( ccw ? 1 : 2 ) ]; + var i3 = indexedFace[ skip + ( ccw ? 2 : 1 ) ]; + + triangulatedIndexArray.push( i1, i2, i3 ); + + skip ++; + + } + + } + + return triangulatedIndexArray; + + } + + var positionIndexes = data.coordIndex ? triangulateIndexArray( data.coordIndex ) : []; + var normalIndexes = data.normalIndex ? triangulateIndexArray( data.normalIndex ) : positionIndexes; + var colorIndexes = data.colorIndex ? triangulateIndexArray( data.colorIndex ) : positionIndexes; + var uvIndexes = data.texCoordIndex ? triangulateIndexArray( data.texCoordIndex ) : positionIndexes; + + var newIndexes = []; var newPositions = []; - var newColors = []; var newNormals = []; + var newColors = []; var newUvs = []; - position = new THREE.Vector3(); - color = new THREE.Color(); - normal = new THREE.Vector3(); - uv = new THREE.Vector2(); + // if any other index array does not match the coordinate indexes, split any points that differ - for ( i = 0, il = data.coordIndex.length; i < il; i ++ ) { + var pointMap = Object.create( null ); - var indexes = data.coordIndex[ i ]; + for ( i = 0; i < positionIndexes.length; i ++ ) { - // VRML support multipoint indexed face sets (more then 3 vertices). You must calculate the composing triangles here + var pointAttributes = []; - skip = 0; + var positionIndex = positionIndexes[ i ]; + var normalIndex = normalIndexes[ i ]; + var colorIndex = colorIndexes[ i ]; + var uvIndex = uvIndexes[ i ]; - while ( indexes.length >= 3 && skip < ( indexes.length - 2 ) ) { + var base = 10; // which base to use to represent each value - if ( data.ccw === undefined ) data.ccw = true; // ccw is true by default + pointAttributes.push( positionIndex.toString( base ) ); - var i1 = indexes[ 0 ]; - var i2 = indexes[ skip + ( data.ccw ? 1 : 2 ) ]; - var i3 = indexes[ skip + ( data.ccw ? 2 : 1 ) ]; + if ( normalIndex !== undefined ) { - // create non indexed geometry, necessary for face normal generation + pointAttributes.push( normalIndex.toString( base ) ); - position.fromArray( positions, i1 * 3 ); - newPositions.push( position.x, position.y, position.z ); - position.fromArray( positions, i2 * 3 ); - newPositions.push( position.x, position.y, position.z ); - position.fromArray( positions, i3 * 3 ); - newPositions.push( position.x, position.y, position.z ); + } - if ( colors.length > 0 ) { + if ( colorIndex !== undefined ) { - color.fromArray( colors, i1 * 3 ); - newColors.push( color.r, color.g, color.b ); - color.fromArray( colors, i2 * 3 ); - newColors.push( color.r, color.g, color.b ); - color.fromArray( colors, i3 * 3 ); - newColors.push( color.r, color.g, color.b ); + pointAttributes.push( colorIndex.toString( base ) ); - } + } - if ( uvs.length > 0 ) { + if ( uvIndex !== undefined ) { - uv.fromArray( uvs, i1 * 2 ); - newUvs.push( uv.x, uv.y ); - uv.fromArray( uvs, i2 * 2 ); - newUvs.push( uv.x, uv.y ); - uv.fromArray( uvs, i3 * 2 ); - newUvs.push( uv.x, uv.y ); + pointAttributes.push( uvIndex.toString( base ) ); + + } + + var pointId = pointAttributes.join( ',' ); + var newIndex = pointMap[ pointId ]; + + if ( newIndex === undefined ) { + + newIndex = newPositions.length / 3; + pointMap[ pointId ] = newIndex; + + newPositions.push( + positions[ positionIndex * 3 ], + positions[ positionIndex * 3 + 1 ], + positions[ positionIndex * 3 + 2 ] + ); + + if ( normalIndex !== undefined && normals.length > 0 ) { + + newNormals.push( + normals[ normalIndex * 3 ], + normals[ normalIndex * 3 + 1 ], + normals[ normalIndex * 3 + 2 ] + ); } - if ( normals.length > 0 ) { + if ( colorIndex !== undefined && colors.length > 0 ) { - normal.fromArray( normals, i1 * 3 ); - newNormals.push( normal.x, normal.y, normal.z ); - normal.fromArray( normals, i2 * 3 ); - newNormals.push( normal.x, normal.y, normal.z ); - normal.fromArray( normals, i3 * 3 ); - newNormals.push( normal.x, normal.y, normal.z ); + newColors.push( + colors[ colorIndex * 3 ], + colors[ colorIndex * 3 + 1 ], + colors[ colorIndex * 3 + 2 ] + ); } - skip ++; + if ( uvIndex !== undefined && uvs.length > 0 ) { + + newUvs.push( + uvs[ uvIndex * 2 ], + uvs[ uvIndex * 2 + 1 ] + ); + + } } + newIndexes.push( newIndex ); + } positions = newPositions; - colors = newColors; normals = newNormals; + color = newColors; uvs = newUvs; + geometry.setIndex( newIndexes ); + } else { // do not add dummy mesh to the scene @@ -1034,6 +1087,8 @@ THREE.VRMLLoader.prototype = { } else { + // convert geometry to non-indexed to get sharp normals + geometry = geometry.toNonIndexed(); geometry.computeVertexNormals(); }