浏览代码

Merge pull request #21060 from mrdoob/modifiers

TessellateModifier: Ported to BufferGeometry.
Mr.doob 4 年之前
父节点
当前提交
2591284fb9

+ 192 - 166
examples/js/modifiers/TessellateModifier.js

@@ -2,273 +2,299 @@
  * Break faces with edges longer than maxEdgeLength
  * Break faces with edges longer than maxEdgeLength
  */
  */
 
 
-THREE.TessellateModifier = function ( maxEdgeLength = 0.1, maxIterations = 6, maxFaces = Infinity ) {
+THREE.TessellateModifier = function ( maxEdgeLength = 0.1, maxIterations = 6 ) {
 
 
 	this.maxEdgeLength = maxEdgeLength;
 	this.maxEdgeLength = maxEdgeLength;
 	this.maxIterations = maxIterations;
 	this.maxIterations = maxIterations;
-	this.maxFaces = maxFaces;
 
 
 };
 };
 
 
-// Applies the "modify" pattern
 THREE.TessellateModifier.prototype.modify = function ( geometry ) {
 THREE.TessellateModifier.prototype.modify = function ( geometry ) {
 
 
-	const isBufferGeometry = geometry.isBufferGeometry;
+	if ( geometry.isGeometry === true ) {
 
 
-	if ( isBufferGeometry ) {
+		console.error( 'THREE.TessellateModifier no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
+		return geometry;
 
 
-		geometry = new THREE.Geometry().fromBufferGeometry( geometry );
+	}
 
 
-	} else {
+	if ( geometry.index !== null ) {
 
 
-		geometry = geometry.clone();
+		geometry = geometry.toNonIndexed();
 
 
 	}
 	}
 
 
-	geometry.mergeVertices( 6 );
+	//
 
 
-	let finalized = false;
-	let iteration = 0;
+	const maxIterations = this.maxIterations;
 	const maxEdgeLengthSquared = this.maxEdgeLength * this.maxEdgeLength;
 	const maxEdgeLengthSquared = this.maxEdgeLength * this.maxEdgeLength;
 
 
-	let edge;
-
-	while ( ! finalized && iteration < this.maxIterations && geometry.faces.length < this.maxFaces ) {
-
-		const faces = [];
-		const faceVertexUvs = [];
-
-		finalized = true;
-		iteration ++;
-
-		for ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
-
-			faceVertexUvs[ i ] = [];
-
-		}
-
-		for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) {
+	const va = new THREE.Vector3();
+	const vb = new THREE.Vector3();
+	const vc = new THREE.Vector3();
+	const vm = new THREE.Vector3();
+	const vs = [ va, vb, vc, vm ];
+
+	const na = new THREE.Vector3();
+	const nb = new THREE.Vector3();
+	const nc = new THREE.Vector3();
+	const nm = new THREE.Vector3();
+	const ns = [ na, nb, nc, nm ];
+
+	const ca = new THREE.Color();
+	const cb = new THREE.Color();
+	const cc = new THREE.Color();
+	const cm = new THREE.Color();
+	const cs = [ ca, cb, cc, cm ];
+
+	const ua = new THREE.Vector2();
+	const ub = new THREE.Vector2();
+	const uc = new THREE.Vector2();
+	const um = new THREE.Vector2();
+	const us = [ ua, ub, uc, um ];
+
+	const u2a = new THREE.Vector2();
+	const u2b = new THREE.Vector2();
+	const u2c = new THREE.Vector2();
+	const u2m = new THREE.Vector2();
+	const u2s = [ u2a, u2b, u2c, u2m ];
+
+	const attributes = geometry.attributes;
+	const hasNormals = attributes.normal !== undefined;
+	const hasColors = attributes.color !== undefined;
+	const hasUVs = attributes.uv !== undefined;
+	const hasUV2s = attributes.uv2 !== undefined;
+
+	let positions = attributes.position.array;
+	let normals = hasNormals ? attributes.normal.array : null;
+	let colors = hasColors ? attributes.color.array : null;
+	let uvs = hasUVs ? attributes.uv.array : null;
+	let uv2s = hasUV2s ? attributes.uv2.array : null;
+
+	let positions2 = positions;
+	let normals2 = normals;
+	let colors2 = colors;
+	let uvs2 = uvs;
+	let uv2s2 = uv2s;
 
 
-			const face = geometry.faces[ i ];
-
-			if ( face instanceof THREE.Face3 ) {
-
-				const a = face.a;
-				const b = face.b;
-				const c = face.c;
-
-				const va = geometry.vertices[ a ];
-				const vb = geometry.vertices[ b ];
-				const vc = geometry.vertices[ c ];
-
-				const dab = va.distanceToSquared( vb );
-				const dbc = vb.distanceToSquared( vc );
-				const dac = va.distanceToSquared( vc );
+	let iteration = 0;
+	let tessellating = true;
 
 
-				const limitReached = ( faces.length + il - i ) >= this.maxFaces;
+	function addTriangle( a, b, c ) {
 
 
-				if ( ! limitReached && ( dab > maxEdgeLengthSquared || dbc > maxEdgeLengthSquared || dac > maxEdgeLengthSquared ) ) {
+		const v1 = vs[ a ];
+		const v2 = vs[ b ];
+		const v3 = vs[ c ];
 
 
-					finalized = false;
+		positions2.push( v1.x, v1.y, v1.z );
+		positions2.push( v2.x, v2.y, v2.z );
+		positions2.push( v3.x, v3.y, v3.z );
 
 
-					const m = geometry.vertices.length;
+		if ( hasNormals ) {
 
 
-					const triA = face.clone();
-					const triB = face.clone();
+			const n1 = ns[ a ];
+			const n2 = ns[ b ];
+			const n3 = ns[ c ];
 
 
-					if ( dab >= dbc && dab >= dac ) {
+			normals2.push( n1.x, n1.y, n1.z );
+			normals2.push( n2.x, n2.y, n2.z );
+			normals2.push( n3.x, n3.y, n3.z );
 
 
-						var vm = va.clone();
-						vm.lerp( vb, 0.5 );
+		}
 
 
-						triA.a = a;
-						triA.b = m;
-						triA.c = c;
+		if ( hasColors ) {
 
 
-						triB.a = m;
-						triB.b = b;
-						triB.c = c;
+			const c1 = cs[ a ];
+			const c2 = cs[ b ];
+			const c3 = cs[ c ];
 
 
-						if ( face.vertexNormals.length === 3 ) {
+			colors2.push( c1.x, c1.y, c1.z );
+			colors2.push( c2.x, c2.y, c2.z );
+			colors2.push( c3.x, c3.y, c3.z );
 
 
-							var vnm = face.vertexNormals[ 0 ].clone();
-							vnm.lerp( face.vertexNormals[ 1 ], 0.5 );
+		}
 
 
-							triA.vertexNormals[ 1 ].copy( vnm );
-							triB.vertexNormals[ 0 ].copy( vnm );
+		if ( hasUVs ) {
 
 
-						}
+			const u1 = us[ a ];
+			const u2 = us[ b ];
+			const u3 = us[ c ];
 
 
-						if ( face.vertexColors.length === 3 ) {
+			uvs2.push( u1.x, u1.y );
+			uvs2.push( u2.x, u2.y );
+			uvs2.push( u3.x, u3.y );
 
 
-							var vcm = face.vertexColors[ 0 ].clone();
-							vcm.lerp( face.vertexColors[ 1 ], 0.5 );
+		}
 
 
-							triA.vertexColors[ 1 ].copy( vcm );
-							triB.vertexColors[ 0 ].copy( vcm );
+		if ( hasUV2s ) {
 
 
-						}
+			const u21 = u2s[ a ];
+			const u22 = u2s[ b ];
+			const u23 = u2s[ c ];
 
 
-						edge = 0;
+			uv2s2.push( u21.x, u21.y );
+			uv2s2.push( u22.x, u22.y );
+			uv2s2.push( u23.x, u23.y );
 
 
-					} else if ( dbc >= dab && dbc >= dac ) {
+		}
 
 
-						var vm = vb.clone();
-						vm.lerp( vc, 0.5 );
+	}
 
 
-						triA.a = a;
-						triA.b = b;
-						triA.c = m;
+	while ( tessellating && iteration < maxIterations ) {
 
 
-						triB.a = m;
-						triB.b = c;
-						triB.c = a;
+		iteration ++;
+		tessellating = false;
 
 
-						if ( face.vertexNormals.length === 3 ) {
+		positions = positions2;
+		positions2 = [];
 
 
-							var vnm = face.vertexNormals[ 1 ].clone();
-							vnm.lerp( face.vertexNormals[ 2 ], 0.5 );
+		if ( hasNormals ) {
 
 
-							triA.vertexNormals[ 2 ].copy( vnm );
+			normals = normals2;
+			normals2 = [];
 
 
-							triB.vertexNormals[ 0 ].copy( vnm );
-							triB.vertexNormals[ 1 ].copy( face.vertexNormals[ 2 ] );
-							triB.vertexNormals[ 2 ].copy( face.vertexNormals[ 0 ] );
+		}
 
 
-						}
+		if ( hasColors ) {
 
 
-						if ( face.vertexColors.length === 3 ) {
+			colors = colors2;
+			colors2 = [];
 
 
-							var vcm = face.vertexColors[ 1 ].clone();
-							vcm.lerp( face.vertexColors[ 2 ], 0.5 );
+		}
 
 
-							triA.vertexColors[ 2 ].copy( vcm );
+		if ( hasUVs ) {
 
 
-							triB.vertexColors[ 0 ].copy( vcm );
-							triB.vertexColors[ 1 ].copy( face.vertexColors[ 2 ] );
-							triB.vertexColors[ 2 ].copy( face.vertexColors[ 0 ] );
+			uvs = uvs2;
+			uvs2 = [];
 
 
-						}
+		}
 
 
-						edge = 1;
+		if ( hasUV2s ) {
 
 
-					} else {
+			uv2s = uv2s2;
+			uv2s2 = [];
 
 
-						var vm = va.clone();
-						vm.lerp( vc, 0.5 );
+		}
 
 
-						triA.a = a;
-						triA.b = b;
-						triA.c = m;
+		for ( var i = 0, i2 = 0, il = positions.length; i < il; i += 9, i2 += 6 ) {
 
 
-						triB.a = m;
-						triB.b = b;
-						triB.c = c;
+			va.fromArray( positions, i + 0 );
+			vb.fromArray( positions, i + 3 );
+			vc.fromArray( positions, i + 6 );
 
 
-						if ( face.vertexNormals.length === 3 ) {
+			if ( hasNormals ) {
 
 
-							var vnm = face.vertexNormals[ 0 ].clone();
-							vnm.lerp( face.vertexNormals[ 2 ], 0.5 );
+				na.fromArray( normals, i + 0 );
+				nb.fromArray( normals, i + 3 );
+				nc.fromArray( normals, i + 6 );
 
 
-							triA.vertexNormals[ 2 ].copy( vnm );
-							triB.vertexNormals[ 0 ].copy( vnm );
+			}
 
 
-						}
+			if ( hasColors ) {
 
 
-						if ( face.vertexColors.length === 3 ) {
+				ca.fromArray( colors, i + 0 );
+				cb.fromArray( colors, i + 3 );
+				cc.fromArray( colors, i + 6 );
 
 
-							var vcm = face.vertexColors[ 0 ].clone();
-							vcm.lerp( face.vertexColors[ 2 ], 0.5 );
+			}
 
 
-							triA.vertexColors[ 2 ].copy( vcm );
-							triB.vertexColors[ 0 ].copy( vcm );
+			if ( hasUVs ) {
 
 
-						}
+				ua.fromArray( uvs, i2 + 0 );
+				ub.fromArray( uvs, i2 + 2 );
+				uc.fromArray( uvs, i2 + 4 );
 
 
-						edge = 2;
+			}
 
 
-					}
+			if ( hasUV2s ) {
 
 
-					faces.push( triA, triB );
-					geometry.vertices.push( vm );
+				u2a.fromArray( uv2s, i2 + 0 );
+				u2b.fromArray( uv2s, i2 + 2 );
+				u2c.fromArray( uv2s, i2 + 4 );
 
 
-					for ( var j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
+			}
 
 
-						if ( geometry.faceVertexUvs[ j ].length ) {
+			const dab = va.distanceToSquared( vb );
+			const dbc = vb.distanceToSquared( vc );
+			const dac = va.distanceToSquared( vc );
 
 
-							const uvs = geometry.faceVertexUvs[ j ][ i ];
+			if ( dab > maxEdgeLengthSquared || dbc > maxEdgeLengthSquared || dac > maxEdgeLengthSquared ) {
 
 
-							const uvA = uvs[ 0 ];
-							const uvB = uvs[ 1 ];
-							const uvC = uvs[ 2 ];
+				tessellating = true;
 
 
-							// AB
+				if ( dab >= dbc && dab >= dac ) {
 
 
-							if ( edge === 0 ) {
+					vm.lerpVectors( va, vb, 0.5 );
+					if ( hasNormals ) nm.lerpVectors( na, nb, 0.5 );
+					if ( hasColors ) cm.lerpColors( ca, cb, 0.5 );
+					if ( hasUVs ) um.lerpVectors( ua, ub, 0.5 );
+					if ( hasUV2s ) u2m.lerpVectors( u2a, u2b, 0.5 );
 
 
-								var uvM = uvA.clone();
-								uvM.lerp( uvB, 0.5 );
+					addTriangle( 0, 3, 2 );
+					addTriangle( 3, 1, 2 );
 
 
-								var uvsTriA = [ uvA.clone(), uvM.clone(), uvC.clone() ];
-								var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
+				} else if ( dbc >= dab && dbc >= dac ) {
 
 
-								// BC
+					vm.lerpVectors( vb, vc, 0.5 );
+					if ( hasNormals ) nm.lerpVectors( nb, nc, 0.5 );
+					if ( hasColors ) cm.lerpColors( cb, cc, 0.5 );
+					if ( hasUVs ) um.lerpVectors( ub, uc, 0.5 );
+					if ( hasUV2s ) u2m.lerpVectors( u2b, u2c, 0.5 );
 
 
-							} else if ( edge === 1 ) {
+					addTriangle( 0, 1, 3 );
+					addTriangle( 3, 2, 0 );
 
 
-								var uvM = uvB.clone();
-								uvM.lerp( uvC, 0.5 );
+				} else {
 
 
-								var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
-								var uvsTriB = [ uvM.clone(), uvC.clone(), uvA.clone() ];
+					vm.lerpVectors( va, vc, 0.5 );
+					if ( hasNormals ) nm.lerpVectors( na, nc, 0.5 );
+					if ( hasColors ) cm.lerpColors( ca, cc, 0.5 );
+					if ( hasUVs ) um.lerpVectors( ua, uc, 0.5 );
+					if ( hasUV2s ) u2m.lerpVectors( u2a, u2c, 0.5 );
 
 
-								// AC
+					addTriangle( 0, 1, 3 );
+					addTriangle( 3, 1, 2 );
 
 
-							} else {
+				}
 
 
-								var uvM = uvA.clone();
-								uvM.lerp( uvC, 0.5 );
+			} else {
 
 
-								var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
-								var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
+				addTriangle( 0, 1, 2 );
 
 
-							}
+			}
 
 
-							faceVertexUvs[ j ].push( uvsTriA, uvsTriB );
+		}
 
 
-						}
+	}
 
 
-					}
+	const geometry2 = new THREE.BufferGeometry();
 
 
-				} else {
+	geometry2.setAttribute( 'position', new THREE.Float32BufferAttribute( positions2, 3 ) );
 
 
-					faces.push( face );
+	if ( hasNormals ) {
 
 
-					for ( var j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
+		geometry2.setAttribute( 'normal', new THREE.Float32BufferAttribute( normals2, 3 ) );
 
 
-						faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] );
+	}
 
 
-					}
+	if ( hasColors ) {
 
 
-				}
+		geometry2.setAttribute( 'color', new THREE.Float32BufferAttribute( colors2, 3 ) );
 
 
-			}
+	}
 
 
-		}
+	if ( hasUVs ) {
 
 
-		geometry.faces = faces;
-		geometry.faceVertexUvs = faceVertexUvs;
+		geometry2.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs2, 2 ) );
 
 
 	}
 	}
 
 
-	if ( isBufferGeometry ) {
-
-		return new THREE.BufferGeometry().fromGeometry( geometry );
+	if ( hasUV2s ) {
 
 
-	} else {
-
-		return geometry;
+		geometry2.setAttribute( 'uv2', new THREE.Float32BufferAttribute( uv2s2, 2 ) );
 
 
 	}
 	}
 
 
+	return geometry2;
+
 };
 };

+ 2 - 3
examples/jsm/modifiers/TessellateModifier.d.ts

@@ -5,11 +5,10 @@ import {
 
 
 export class TessellateModifier {
 export class TessellateModifier {
 
 
-	constructor( maxEdgeLength?: number, maxIterations?: number, maxFaces?: number );
+	constructor( maxEdgeLength?: number, maxIterations?: number );
 	maxEdgeLength: number = 0.1;
 	maxEdgeLength: number = 0.1;
 	maxIterations: number = 6;
 	maxIterations: number = 6;
-	maxFaces: number = Infinity;
 
 
-	modify( geometry: Geometry | BufferGeometry ): Geometry | BufferGeometry;
+	modify( geometry: BufferGeometry ): BufferGeometry;
 
 
 }
 }

+ 197 - 168
examples/jsm/modifiers/TessellateModifier.js

@@ -1,282 +1,311 @@
 import {
 import {
 	BufferGeometry,
 	BufferGeometry,
-	Face3,
-	Geometry
+	Color,
+	Float32BufferAttribute,
+	Geometry,
+	Vector2,
+	Vector3
 } from '../../../build/three.module.js';
 } from '../../../build/three.module.js';
 
 
 /**
 /**
  * Break faces with edges longer than maxEdgeLength
  * Break faces with edges longer than maxEdgeLength
  */
  */
 
 
-var TessellateModifier = function ( maxEdgeLength = 0.1, maxIterations = 6, maxFaces = Infinity ) {
+var TessellateModifier = function ( maxEdgeLength = 0.1, maxIterations = 6 ) {
 
 
 	this.maxEdgeLength = maxEdgeLength;
 	this.maxEdgeLength = maxEdgeLength;
 	this.maxIterations = maxIterations;
 	this.maxIterations = maxIterations;
-	this.maxFaces = maxFaces;
 
 
 };
 };
 
 
-// Applies the "modify" pattern
 TessellateModifier.prototype.modify = function ( geometry ) {
 TessellateModifier.prototype.modify = function ( geometry ) {
 
 
-	const isBufferGeometry = geometry.isBufferGeometry;
+	if ( geometry.isGeometry === true ) {
 
 
-	if ( isBufferGeometry ) {
+		console.error( 'THREE.TessellateModifier no longer supports Geometry. Use BufferGeometry instead.' );
+		return geometry;
 
 
-		geometry = new Geometry().fromBufferGeometry( geometry );
+	}
 
 
-	} else {
+	if ( geometry.index !== null ) {
 
 
-		geometry = geometry.clone();
+		geometry = geometry.toNonIndexed();
 
 
 	}
 	}
 
 
-	geometry.mergeVertices( 6 );
+	//
 
 
-	let finalized = false;
-	let iteration = 0;
+	const maxIterations = this.maxIterations;
 	const maxEdgeLengthSquared = this.maxEdgeLength * this.maxEdgeLength;
 	const maxEdgeLengthSquared = this.maxEdgeLength * this.maxEdgeLength;
 
 
-	let edge;
-
-	while ( ! finalized && iteration < this.maxIterations && geometry.faces.length < this.maxFaces ) {
-
-		const faces = [];
-		const faceVertexUvs = [];
-
-		finalized = true;
-		iteration ++;
-
-		for ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
-
-			faceVertexUvs[ i ] = [];
-
-		}
-
-		for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) {
+	const va = new Vector3();
+	const vb = new Vector3();
+	const vc = new Vector3();
+	const vm = new Vector3();
+	const vs = [ va, vb, vc, vm ];
+
+	const na = new Vector3();
+	const nb = new Vector3();
+	const nc = new Vector3();
+	const nm = new Vector3();
+	const ns = [ na, nb, nc, nm ];
+
+	const ca = new Color();
+	const cb = new Color();
+	const cc = new Color();
+	const cm = new Color();
+	const cs = [ ca, cb, cc, cm ];
+
+	const ua = new Vector2();
+	const ub = new Vector2();
+	const uc = new Vector2();
+	const um = new Vector2();
+	const us = [ ua, ub, uc, um ];
+
+	const u2a = new Vector2();
+	const u2b = new Vector2();
+	const u2c = new Vector2();
+	const u2m = new Vector2();
+	const u2s = [ u2a, u2b, u2c, u2m ];
+
+	const attributes = geometry.attributes;
+	const hasNormals = attributes.normal !== undefined;
+	const hasColors = attributes.color !== undefined;
+	const hasUVs = attributes.uv !== undefined;
+	const hasUV2s = attributes.uv2 !== undefined;
+
+	let positions = attributes.position.array;
+	let normals = hasNormals ? attributes.normal.array : null;
+	let colors = hasColors ? attributes.color.array : null;
+	let uvs = hasUVs ? attributes.uv.array : null;
+	let uv2s = hasUV2s ? attributes.uv2.array : null;
+
+	let positions2 = positions;
+	let normals2 = normals;
+	let colors2 = colors;
+	let uvs2 = uvs;
+	let uv2s2 = uv2s;
 
 
-			const face = geometry.faces[ i ];
-
-			if ( face instanceof Face3 ) {
-
-				const a = face.a;
-				const b = face.b;
-				const c = face.c;
-
-				const va = geometry.vertices[ a ];
-				const vb = geometry.vertices[ b ];
-				const vc = geometry.vertices[ c ];
-
-				const dab = va.distanceToSquared( vb );
-				const dbc = vb.distanceToSquared( vc );
-				const dac = va.distanceToSquared( vc );
+	let iteration = 0;
+	let tessellating = true;
 
 
-				const limitReached = ( faces.length + il - i ) >= this.maxFaces;
+	function addTriangle( a, b, c ) {
 
 
-				if ( ! limitReached && ( dab > maxEdgeLengthSquared || dbc > maxEdgeLengthSquared || dac > maxEdgeLengthSquared ) ) {
+		const v1 = vs[ a ];
+		const v2 = vs[ b ];
+		const v3 = vs[ c ];
 
 
-					finalized = false;
+		positions2.push( v1.x, v1.y, v1.z );
+		positions2.push( v2.x, v2.y, v2.z );
+		positions2.push( v3.x, v3.y, v3.z );
 
 
-					const m = geometry.vertices.length;
+		if ( hasNormals ) {
 
 
-					const triA = face.clone();
-					const triB = face.clone();
+			const n1 = ns[ a ];
+			const n2 = ns[ b ];
+			const n3 = ns[ c ];
 
 
-					if ( dab >= dbc && dab >= dac ) {
+			normals2.push( n1.x, n1.y, n1.z );
+			normals2.push( n2.x, n2.y, n2.z );
+			normals2.push( n3.x, n3.y, n3.z );
 
 
-						var vm = va.clone();
-						vm.lerp( vb, 0.5 );
+		}
 
 
-						triA.a = a;
-						triA.b = m;
-						triA.c = c;
+		if ( hasColors ) {
 
 
-						triB.a = m;
-						triB.b = b;
-						triB.c = c;
+			const c1 = cs[ a ];
+			const c2 = cs[ b ];
+			const c3 = cs[ c ];
 
 
-						if ( face.vertexNormals.length === 3 ) {
+			colors2.push( c1.x, c1.y, c1.z );
+			colors2.push( c2.x, c2.y, c2.z );
+			colors2.push( c3.x, c3.y, c3.z );
 
 
-							var vnm = face.vertexNormals[ 0 ].clone();
-							vnm.lerp( face.vertexNormals[ 1 ], 0.5 );
+		}
 
 
-							triA.vertexNormals[ 1 ].copy( vnm );
-							triB.vertexNormals[ 0 ].copy( vnm );
+		if ( hasUVs ) {
 
 
-						}
+			const u1 = us[ a ];
+			const u2 = us[ b ];
+			const u3 = us[ c ];
 
 
-						if ( face.vertexColors.length === 3 ) {
+			uvs2.push( u1.x, u1.y );
+			uvs2.push( u2.x, u2.y );
+			uvs2.push( u3.x, u3.y );
 
 
-							var vcm = face.vertexColors[ 0 ].clone();
-							vcm.lerp( face.vertexColors[ 1 ], 0.5 );
+		}
 
 
-							triA.vertexColors[ 1 ].copy( vcm );
-							triB.vertexColors[ 0 ].copy( vcm );
+		if ( hasUV2s ) {
 
 
-						}
+			const u21 = u2s[ a ];
+			const u22 = u2s[ b ];
+			const u23 = u2s[ c ];
 
 
-						edge = 0;
+			uv2s2.push( u21.x, u21.y );
+			uv2s2.push( u22.x, u22.y );
+			uv2s2.push( u23.x, u23.y );
 
 
-					} else if ( dbc >= dab && dbc >= dac ) {
+		}
 
 
-						var vm = vb.clone();
-						vm.lerp( vc, 0.5 );
+	}
 
 
-						triA.a = a;
-						triA.b = b;
-						triA.c = m;
+	while ( tessellating && iteration < maxIterations ) {
 
 
-						triB.a = m;
-						triB.b = c;
-						triB.c = a;
+		iteration ++;
+		tessellating = false;
 
 
-						if ( face.vertexNormals.length === 3 ) {
+		positions = positions2;
+		positions2 = [];
 
 
-							var vnm = face.vertexNormals[ 1 ].clone();
-							vnm.lerp( face.vertexNormals[ 2 ], 0.5 );
+		if ( hasNormals ) {
 
 
-							triA.vertexNormals[ 2 ].copy( vnm );
+			normals = normals2;
+			normals2 = [];
 
 
-							triB.vertexNormals[ 0 ].copy( vnm );
-							triB.vertexNormals[ 1 ].copy( face.vertexNormals[ 2 ] );
-							triB.vertexNormals[ 2 ].copy( face.vertexNormals[ 0 ] );
+		}
 
 
-						}
+		if ( hasColors ) {
 
 
-						if ( face.vertexColors.length === 3 ) {
+			colors = colors2;
+			colors2 = [];
 
 
-							var vcm = face.vertexColors[ 1 ].clone();
-							vcm.lerp( face.vertexColors[ 2 ], 0.5 );
+		}
 
 
-							triA.vertexColors[ 2 ].copy( vcm );
+		if ( hasUVs ) {
 
 
-							triB.vertexColors[ 0 ].copy( vcm );
-							triB.vertexColors[ 1 ].copy( face.vertexColors[ 2 ] );
-							triB.vertexColors[ 2 ].copy( face.vertexColors[ 0 ] );
+			uvs = uvs2;
+			uvs2 = [];
 
 
-						}
+		}
 
 
-						edge = 1;
+		if ( hasUV2s ) {
 
 
-					} else {
+			uv2s = uv2s2;
+			uv2s2 = [];
 
 
-						var vm = va.clone();
-						vm.lerp( vc, 0.5 );
+		}
 
 
-						triA.a = a;
-						triA.b = b;
-						triA.c = m;
+		for ( var i = 0, i2 = 0, il = positions.length; i < il; i += 9, i2 += 6 ) {
 
 
-						triB.a = m;
-						triB.b = b;
-						triB.c = c;
+			va.fromArray( positions, i + 0 );
+			vb.fromArray( positions, i + 3 );
+			vc.fromArray( positions, i + 6 );
 
 
-						if ( face.vertexNormals.length === 3 ) {
+			if ( hasNormals ) {
 
 
-							var vnm = face.vertexNormals[ 0 ].clone();
-							vnm.lerp( face.vertexNormals[ 2 ], 0.5 );
+				na.fromArray( normals, i + 0 );
+				nb.fromArray( normals, i + 3 );
+				nc.fromArray( normals, i + 6 );
 
 
-							triA.vertexNormals[ 2 ].copy( vnm );
-							triB.vertexNormals[ 0 ].copy( vnm );
+			}
 
 
-						}
+			if ( hasColors ) {
 
 
-						if ( face.vertexColors.length === 3 ) {
+				ca.fromArray( colors, i + 0 );
+				cb.fromArray( colors, i + 3 );
+				cc.fromArray( colors, i + 6 );
 
 
-							var vcm = face.vertexColors[ 0 ].clone();
-							vcm.lerp( face.vertexColors[ 2 ], 0.5 );
+			}
 
 
-							triA.vertexColors[ 2 ].copy( vcm );
-							triB.vertexColors[ 0 ].copy( vcm );
+			if ( hasUVs ) {
 
 
-						}
+				ua.fromArray( uvs, i2 + 0 );
+				ub.fromArray( uvs, i2 + 2 );
+				uc.fromArray( uvs, i2 + 4 );
 
 
-						edge = 2;
+			}
 
 
-					}
+			if ( hasUV2s ) {
 
 
-					faces.push( triA, triB );
-					geometry.vertices.push( vm );
+				u2a.fromArray( uv2s, i2 + 0 );
+				u2b.fromArray( uv2s, i2 + 2 );
+				u2c.fromArray( uv2s, i2 + 4 );
 
 
-					for ( var j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
+			}
 
 
-						if ( geometry.faceVertexUvs[ j ].length ) {
+			const dab = va.distanceToSquared( vb );
+			const dbc = vb.distanceToSquared( vc );
+			const dac = va.distanceToSquared( vc );
 
 
-							const uvs = geometry.faceVertexUvs[ j ][ i ];
+			if ( dab > maxEdgeLengthSquared || dbc > maxEdgeLengthSquared || dac > maxEdgeLengthSquared ) {
 
 
-							const uvA = uvs[ 0 ];
-							const uvB = uvs[ 1 ];
-							const uvC = uvs[ 2 ];
+				tessellating = true;
 
 
-							// AB
+				if ( dab >= dbc && dab >= dac ) {
 
 
-							if ( edge === 0 ) {
+					vm.lerpVectors( va, vb, 0.5 );
+					if ( hasNormals ) nm.lerpVectors( na, nb, 0.5 );
+					if ( hasColors ) cm.lerpColors( ca, cb, 0.5 );
+					if ( hasUVs ) um.lerpVectors( ua, ub, 0.5 );
+					if ( hasUV2s ) u2m.lerpVectors( u2a, u2b, 0.5 );
 
 
-								var uvM = uvA.clone();
-								uvM.lerp( uvB, 0.5 );
+					addTriangle( 0, 3, 2 );
+					addTriangle( 3, 1, 2 );
 
 
-								var uvsTriA = [ uvA.clone(), uvM.clone(), uvC.clone() ];
-								var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
+				} else if ( dbc >= dab && dbc >= dac ) {
 
 
-								// BC
+					vm.lerpVectors( vb, vc, 0.5 );
+					if ( hasNormals ) nm.lerpVectors( nb, nc, 0.5 );
+					if ( hasColors ) cm.lerpColors( cb, cc, 0.5 );
+					if ( hasUVs ) um.lerpVectors( ub, uc, 0.5 );
+					if ( hasUV2s ) u2m.lerpVectors( u2b, u2c, 0.5 );
 
 
-							} else if ( edge === 1 ) {
+					addTriangle( 0, 1, 3 );
+					addTriangle( 3, 2, 0 );
 
 
-								var uvM = uvB.clone();
-								uvM.lerp( uvC, 0.5 );
+				} else {
 
 
-								var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
-								var uvsTriB = [ uvM.clone(), uvC.clone(), uvA.clone() ];
+					vm.lerpVectors( va, vc, 0.5 );
+					if ( hasNormals ) nm.lerpVectors( na, nc, 0.5 );
+					if ( hasColors ) cm.lerpColors( ca, cc, 0.5 );
+					if ( hasUVs ) um.lerpVectors( ua, uc, 0.5 );
+					if ( hasUV2s ) u2m.lerpVectors( u2a, u2c, 0.5 );
 
 
-								// AC
+					addTriangle( 0, 1, 3 );
+					addTriangle( 3, 1, 2 );
 
 
-							} else {
+				}
 
 
-								var uvM = uvA.clone();
-								uvM.lerp( uvC, 0.5 );
+			} else {
 
 
-								var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
-								var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
+				addTriangle( 0, 1, 2 );
 
 
-							}
+			}
 
 
-							faceVertexUvs[ j ].push( uvsTriA, uvsTriB );
+		}
 
 
-						}
+	}
 
 
-					}
+	const geometry2 = new BufferGeometry();
 
 
-				} else {
+	geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
 
 
-					faces.push( face );
+	if ( hasNormals ) {
 
 
-					for ( var j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
+		geometry2.setAttribute( 'normal', new Float32BufferAttribute( normals2, 3 ) );
 
 
-						faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] );
+	}
 
 
-					}
+	if ( hasColors ) {
 
 
-				}
+		geometry2.setAttribute( 'color', new Float32BufferAttribute( colors2, 3 ) );
 
 
-			}
+	}
 
 
-		}
+	if ( hasUVs ) {
 
 
-		geometry.faces = faces;
-		geometry.faceVertexUvs = faceVertexUvs;
+		geometry2.setAttribute( 'uv', new Float32BufferAttribute( uvs2, 2 ) );
 
 
 	}
 	}
 
 
-	if ( isBufferGeometry ) {
-
-		return new BufferGeometry().fromGeometry( geometry );
+	if ( hasUV2s ) {
 
 
-	} else {
-
-		return geometry;
+		geometry2.setAttribute( 'uv2', new Float32BufferAttribute( uv2s2, 2 ) );
 
 
 	}
 	}
 
 
+	return geometry2;
+
 };
 };
 
 
 export { TessellateModifier };
 export { TessellateModifier };

+ 1 - 1
src/core/BufferGeometry.js

@@ -926,7 +926,7 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
 
 		if ( this.index === null ) {
 		if ( this.index === null ) {
 
 
-			console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
+			console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
 			return this;
 			return this;
 
 
 		}
 		}