/** * Break faces with edges longer than maxEdgeLength * - not recursive * * @author alteredq / http://alteredqualia.com/ */ THREE.TessellateModifier = function ( maxEdgeLength ) { this.maxEdgeLength = maxEdgeLength; }; THREE.TessellateModifier.prototype.modify = function ( geometry ) { var edge; var faces = []; var faceVertexUvs = []; var maxEdgeLengthSquared = this.maxEdgeLength * this.maxEdgeLength; for ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) { faceVertexUvs[ i ] = []; } for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) { var face = geometry.faces[ i ]; if ( face instanceof THREE.Face3 ) { var a = face.a; var b = face.b; var c = face.c; var va = geometry.vertices[ a ]; var vb = geometry.vertices[ b ]; var vc = geometry.vertices[ c ]; var dab = va.distanceToSquared( vb ); var dbc = vb.distanceToSquared( vc ); var dac = va.distanceToSquared( vc ); if ( dab > maxEdgeLengthSquared || dbc > maxEdgeLengthSquared || dac > maxEdgeLengthSquared ) { var m = geometry.vertices.length; var triA = face.clone(); var triB = face.clone(); if ( dab >= dbc && dab >= dac ) { var vm = va.clone(); vm.lerp( vb, 0.5 ); triA.a = a; triA.b = m; triA.c = c; triB.a = m; triB.b = b; triB.c = c; if ( face.vertexNormals.length === 3 ) { var vnm = face.vertexNormals[ 0 ].clone(); vnm.lerp( face.vertexNormals[ 1 ], 0.5 ); triA.vertexNormals[ 1 ].copy( vnm ); triB.vertexNormals[ 0 ].copy( vnm ); } if ( face.vertexColors.length === 3 ) { var vcm = face.vertexColors[ 0 ].clone(); vcm.lerp( face.vertexColors[ 1 ], 0.5 ); triA.vertexColors[ 1 ].copy( vcm ); triB.vertexColors[ 0 ].copy( vcm ); } edge = 0; } else if ( dbc >= dab && dbc >= dac ) { var vm = vb.clone(); vm.lerp( vc, 0.5 ); triA.a = a; triA.b = b; triA.c = m; triB.a = m; triB.b = c; triB.c = a; if ( face.vertexNormals.length === 3 ) { var vnm = face.vertexNormals[ 1 ].clone(); vnm.lerp( face.vertexNormals[ 2 ], 0.5 ); triA.vertexNormals[ 2 ].copy( vnm ); triB.vertexNormals[ 0 ].copy( vnm ); triB.vertexNormals[ 1 ].copy( face.vertexNormals[ 2 ] ); triB.vertexNormals[ 2 ].copy( face.vertexNormals[ 0 ] ); } if ( face.vertexColors.length === 3 ) { var vcm = face.vertexColors[ 1 ].clone(); vcm.lerp( face.vertexColors[ 2 ], 0.5 ); triA.vertexColors[ 2 ].copy( vcm ); triB.vertexColors[ 0 ].copy( vcm ); triB.vertexColors[ 1 ].copy( face.vertexColors[ 2 ] ); triB.vertexColors[ 2 ].copy( face.vertexColors[ 0 ] ); } edge = 1; } else { var vm = va.clone(); vm.lerp( vc, 0.5 ); triA.a = a; triA.b = b; triA.c = m; triB.a = m; triB.b = b; triB.c = c; if ( face.vertexNormals.length === 3 ) { var vnm = face.vertexNormals[ 0 ].clone(); vnm.lerp( face.vertexNormals[ 2 ], 0.5 ); triA.vertexNormals[ 2 ].copy( vnm ); triB.vertexNormals[ 0 ].copy( vnm ); } if ( face.vertexColors.length === 3 ) { var vcm = face.vertexColors[ 0 ].clone(); vcm.lerp( face.vertexColors[ 2 ], 0.5 ); triA.vertexColors[ 2 ].copy( vcm ); triB.vertexColors[ 0 ].copy( vcm ); } edge = 2; } faces.push( triA, triB ); geometry.vertices.push( vm ); for ( var j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) { if ( geometry.faceVertexUvs[ j ].length ) { var uvs = geometry.faceVertexUvs[ j ][ i ]; var uvA = uvs[ 0 ]; var uvB = uvs[ 1 ]; var uvC = uvs[ 2 ]; // AB if ( edge === 0 ) { var uvM = uvA.clone(); uvM.lerp( uvB, 0.5 ); var uvsTriA = [ uvA.clone(), uvM.clone(), uvC.clone() ]; var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ]; // BC } else if ( edge === 1 ) { var uvM = uvB.clone(); uvM.lerp( uvC, 0.5 ); var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ]; var uvsTriB = [ uvM.clone(), uvC.clone(), uvA.clone() ]; // AC } else { var uvM = uvA.clone(); uvM.lerp( uvC, 0.5 ); var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ]; var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ]; } faceVertexUvs[ j ].push( uvsTriA, uvsTriB ); } } } else { faces.push( face ); for ( var j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) { faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] ); } } } } geometry.faces = faces; geometry.faceVertexUvs = faceVertexUvs; };