Bläddra i källkod

TubePainter: Replace disk caps with hemisphere caps.

Mr.doob 2 månader sedan
förälder
incheckning
21009ebc44
1 ändrade filer med 181 tillägg och 45 borttagningar
  1. 181 45
      examples/jsm/misc/TubePainter.js

+ 181 - 45
examples/jsm/misc/TubePainter.js

@@ -53,7 +53,7 @@ function TubePainter() {
 
 		const PI2 = Math.PI * 2;
 
-		const sides = 10;
+		const sides = 15;
 		const array = [];
 		const radius = 0.01 * size;
 
@@ -88,37 +88,118 @@ function TubePainter() {
 		let count = geometry.drawRange.count;
 
 		const points = getPoints( capSize );
+		const sides = points.length;
+		const radius = 0.01 * capSize;
+		const latSegments = 4;
+		const directionSign = isEndCap ? - 1 : 1;
 
-		const normalSign = isEndCap ? - 1 : 1;
+		for ( let lat = 0; lat < latSegments; lat ++ ) {
 
-		normal.set(
-			matrix.elements[ 8 ] * normalSign,
-			matrix.elements[ 9 ] * normalSign,
-			matrix.elements[ 10 ] * normalSign
-		).normalize();
+			const phi1 = ( lat / latSegments ) * Math.PI * 0.5;
+			const phi2 = ( ( lat + 1 ) / latSegments ) * Math.PI * 0.5;
 
-		for ( let i = 0, il = points.length; i < il; i ++ ) {
+			const z1 = Math.sin( phi1 ) * radius * directionSign;
+			const r1 = Math.cos( phi1 ) * radius;
 
-			const vertex1 = points[ i ];
-			const vertex2 = points[ ( i + 1 ) % il ];
+			const z2 = Math.sin( phi2 ) * radius * directionSign;
+			const r2 = Math.cos( phi2 ) * radius;
 
-			vector1.copy( position );
-			vector2.copy( isEndCap ? vertex1 : vertex2 ).applyMatrix4( matrix ).add( position );
-			vector3.copy( isEndCap ? vertex2 : vertex1 ).applyMatrix4( matrix ).add( position );
+			for ( let i = 0; i < sides; i ++ ) {
 
-			vector1.toArray( positions.array, ( count + 0 ) * 3 );
-			vector2.toArray( positions.array, ( count + 1 ) * 3 );
-			vector3.toArray( positions.array, ( count + 2 ) * 3 );
+				const theta1 = ( i / sides ) * Math.PI * 2;
+				const theta2 = ( ( i + 1 ) / sides ) * Math.PI * 2;
 
-			normal.toArray( normals.array, ( count + 0 ) * 3 );
-			normal.toArray( normals.array, ( count + 1 ) * 3 );
-			normal.toArray( normals.array, ( count + 2 ) * 3 );
+				// First ring
+				const x1 = Math.sin( theta1 ) * r1;
+				const y1 = Math.cos( theta1 ) * r1;
 
-			color1.toArray( colors.array, ( count + 0 ) * 3 );
-			color1.toArray( colors.array, ( count + 1 ) * 3 );
-			color1.toArray( colors.array, ( count + 2 ) * 3 );
+				const x2 = Math.sin( theta2 ) * r1;
+				const y2 = Math.cos( theta2 ) * r1;
+
+				// Second ring
+				const x3 = Math.sin( theta1 ) * r2;
+				const y3 = Math.cos( theta1 ) * r2;
+
+				const x4 = Math.sin( theta2 ) * r2;
+				const y4 = Math.cos( theta2 ) * r2;
+
+				// Transform to world space
+				vector1.set( x1, y1, z1 ).applyMatrix4( matrix ).add( position );
+				vector2.set( x2, y2, z1 ).applyMatrix4( matrix ).add( position );
+				vector3.set( x3, y3, z2 ).applyMatrix4( matrix ).add( position );
+				vector4.set( x4, y4, z2 ).applyMatrix4( matrix ).add( position );
+
+				// First triangle
+				normal.set( x1, y1, z1 ).normalize().transformDirection( matrix );
+				vector.set( x2, y2, z1 ).normalize().transformDirection( matrix );
+				side.set( x3, y3, z2 ).normalize().transformDirection( matrix );
+
+				if ( isEndCap ) {
+
+					vector1.toArray( positions.array, count * 3 );
+					vector2.toArray( positions.array, ( count + 1 ) * 3 );
+					vector3.toArray( positions.array, ( count + 2 ) * 3 );
+
+					normal.toArray( normals.array, count * 3 );
+					vector.toArray( normals.array, ( count + 1 ) * 3 );
+					side.toArray( normals.array, ( count + 2 ) * 3 );
+
+				} else {
+
+					vector1.toArray( positions.array, count * 3 );
+					vector3.toArray( positions.array, ( count + 1 ) * 3 );
+					vector2.toArray( positions.array, ( count + 2 ) * 3 );
+
+					normal.toArray( normals.array, count * 3 );
+					side.toArray( normals.array, ( count + 1 ) * 3 );
+					vector.toArray( normals.array, ( count + 2 ) * 3 );
+
+				}
+
+				color1.toArray( colors.array, count * 3 );
+				color1.toArray( colors.array, ( count + 1 ) * 3 );
+				color1.toArray( colors.array, ( count + 2 ) * 3 );
+
+				count += 3;
+
+				// Second triangle
+				if ( r2 > 0.001 ) {
+
+					normal.set( x2, y2, z1 ).normalize().transformDirection( matrix );
+					vector.set( x4, y4, z2 ).normalize().transformDirection( matrix );
+					side.set( x3, y3, z2 ).normalize().transformDirection( matrix );
+
+					if ( isEndCap ) {
+
+						vector2.toArray( positions.array, count * 3 );
+						vector4.toArray( positions.array, ( count + 1 ) * 3 );
+						vector3.toArray( positions.array, ( count + 2 ) * 3 );
+
+						normal.toArray( normals.array, count * 3 );
+						vector.toArray( normals.array, ( count + 1 ) * 3 );
+						side.toArray( normals.array, ( count + 2 ) * 3 );
+
+					} else {
+
+						vector3.toArray( positions.array, count * 3 );
+						vector4.toArray( positions.array, ( count + 1 ) * 3 );
+						vector2.toArray( positions.array, ( count + 2 ) * 3 );
+
+						side.toArray( normals.array, count * 3 );
+						vector.toArray( normals.array, ( count + 1 ) * 3 );
+						normal.toArray( normals.array, ( count + 2 ) * 3 );
+
+					}
+
+					color1.toArray( colors.array, count * 3 );
+					color1.toArray( colors.array, ( count + 1 ) * 3 );
+					color1.toArray( colors.array, ( count + 2 ) * 3 );
 
-			count += 3;
+					count += 3;
+
+				}
+
+			}
 
 		}
 
@@ -131,37 +212,92 @@ function TubePainter() {
 		if ( endCapStartIndex === null ) return;
 
 		const points = getPoints( capSize );
-
-		normal.set(
-			- matrix.elements[ 8 ],
-			- matrix.elements[ 9 ],
-			- matrix.elements[ 10 ]
-		).normalize();
+		const sides = points.length;
+		const radius = 0.01 * capSize;
+		const latSegments = 4;
 
 		let count = endCapStartIndex;
 
-		for ( let i = 0, il = points.length; i < il; i ++ ) {
+		for ( let lat = 0; lat < latSegments; lat ++ ) {
 
-			const vertex1 = points[ i ];
-			const vertex2 = points[ ( i + 1 ) % il ];
+			const phi1 = ( lat / latSegments ) * Math.PI * 0.5;
+			const phi2 = ( ( lat + 1 ) / latSegments ) * Math.PI * 0.5;
 
-			vector1.copy( position );
-			vector2.copy( vertex1 ).applyMatrix4( matrix ).add( position );
-			vector3.copy( vertex2 ).applyMatrix4( matrix ).add( position );
+			const z1 = - Math.sin( phi1 ) * radius;
+			const r1 = Math.cos( phi1 ) * radius;
 
-			vector1.toArray( positions.array, ( count + 0 ) * 3 );
-			vector2.toArray( positions.array, ( count + 1 ) * 3 );
-			vector3.toArray( positions.array, ( count + 2 ) * 3 );
+			const z2 = - Math.sin( phi2 ) * radius;
+			const r2 = Math.cos( phi2 ) * radius;
 
-			normal.toArray( normals.array, ( count + 0 ) * 3 );
-			normal.toArray( normals.array, ( count + 1 ) * 3 );
-			normal.toArray( normals.array, ( count + 2 ) * 3 );
+			for ( let i = 0; i < sides; i ++ ) {
 
-			color1.toArray( colors.array, ( count + 0 ) * 3 );
-			color1.toArray( colors.array, ( count + 1 ) * 3 );
-			color1.toArray( colors.array, ( count + 2 ) * 3 );
+				const theta1 = ( i / sides ) * Math.PI * 2;
+				const theta2 = ( ( i + 1 ) / sides ) * Math.PI * 2;
+
+				// First ring
+				const x1 = Math.sin( theta1 ) * r1;
+				const y1 = Math.cos( theta1 ) * r1;
+
+				const x2 = Math.sin( theta2 ) * r1;
+				const y2 = Math.cos( theta2 ) * r1;
+
+				// Second ring
+				const x3 = Math.sin( theta1 ) * r2;
+				const y3 = Math.cos( theta1 ) * r2;
+
+				const x4 = Math.sin( theta2 ) * r2;
+				const y4 = Math.cos( theta2 ) * r2;
+
+				// Transform positions to world space
+				vector1.set( x1, y1, z1 ).applyMatrix4( matrix ).add( position );
+				vector2.set( x2, y2, z1 ).applyMatrix4( matrix ).add( position );
+				vector3.set( x3, y3, z2 ).applyMatrix4( matrix ).add( position );
+				vector4.set( x4, y4, z2 ).applyMatrix4( matrix ).add( position );
+
+				// Transform normals to world space
+				normal.set( x1, y1, z1 ).normalize().transformDirection( matrix );
+				vector.set( x2, y2, z1 ).normalize().transformDirection( matrix );
+				side.set( x3, y3, z2 ).normalize().transformDirection( matrix );
 
-			count += 3;
+				// First triangle
+				vector1.toArray( positions.array, count * 3 );
+				vector2.toArray( positions.array, ( count + 1 ) * 3 );
+				vector3.toArray( positions.array, ( count + 2 ) * 3 );
+
+				normal.toArray( normals.array, count * 3 );
+				vector.toArray( normals.array, ( count + 1 ) * 3 );
+				side.toArray( normals.array, ( count + 2 ) * 3 );
+
+				color1.toArray( colors.array, count * 3 );
+				color1.toArray( colors.array, ( count + 1 ) * 3 );
+				color1.toArray( colors.array, ( count + 2 ) * 3 );
+
+				count += 3;
+
+				// Second triangle
+				if ( r2 > 0.001 ) {
+
+					normal.set( x2, y2, z1 ).normalize().transformDirection( matrix );
+					vector.set( x4, y4, z2 ).normalize().transformDirection( matrix );
+					side.set( x3, y3, z2 ).normalize().transformDirection( matrix );
+
+					vector2.toArray( positions.array, count * 3 );
+					vector4.toArray( positions.array, ( count + 1 ) * 3 );
+					vector3.toArray( positions.array, ( count + 2 ) * 3 );
+
+					normal.toArray( normals.array, count * 3 );
+					vector.toArray( normals.array, ( count + 1 ) * 3 );
+					side.toArray( normals.array, ( count + 2 ) * 3 );
+
+					color1.toArray( colors.array, count * 3 );
+					color1.toArray( colors.array, ( count + 1 ) * 3 );
+					color1.toArray( colors.array, ( count + 2 ) * 3 );
+
+					count += 3;
+
+				}
+
+			}
 
 		}
 

粤ICP备19079148号