Răsfoiți Sursa

Merge pull request #20632 from gkjohnson/rounded-box-uvs

Fix RoundedBoxBufferGeometry UVs
Mr.doob 4 ani în urmă
părinte
comite
4ca54c132d
1 a modificat fișierele cu 70 adăugiri și 12 ștergeri
  1. 70 12
      examples/jsm/geometries/RoundedBoxBufferGeometry.js

+ 70 - 12
examples/jsm/geometries/RoundedBoxBufferGeometry.js

@@ -3,6 +3,40 @@ import {
 	Vector3
 } from "../../../build/three.module.js";
 
+const tempNormal = new Vector3();
+function getUv( faceDirVector, normal, uvAxis, projectionAxis, radius, sideLength ) {
+
+	const totArcLength = 2 * Math.PI * radius / 4;
+
+	// length of the planes between the arcs on each axis
+	const centerLength = Math.max( sideLength - 2 * radius, 0 );
+	const halfArc = Math.PI / 4;
+
+	// Get the vector projected onto the Y plane
+	tempNormal.copy( normal );
+	tempNormal[ projectionAxis ] = 0;
+	tempNormal.normalize();
+
+	// total amount of UV space alloted to a single arc
+	const arcUvRatio = 0.5 * totArcLength / ( totArcLength + centerLength );
+
+	// the distance along one arc the point is at
+	const arcAngleRatio = 1.0 - ( tempNormal.angleTo( faceDirVector ) / halfArc );
+
+	if ( Math.sign( tempNormal[ uvAxis ] ) === 1 ) {
+
+		return arcAngleRatio * arcUvRatio;
+
+	} else {
+
+		// total amount of UV space alloted to the plane between the arcs
+		const lenUv = centerLength / ( totArcLength + centerLength );
+		return lenUv + arcUvRatio + arcUvRatio * ( 1.0 - arcAngleRatio );
+
+	}
+
+}
+
 class RoundedBoxBufferGeometry extends BoxBufferGeometry {
 
 	constructor( width = 1, height = 1, depth = 1, segments = 1, radius = 1 ) {
@@ -28,6 +62,7 @@ class RoundedBoxBufferGeometry extends BoxBufferGeometry {
 		const uvs = this.attributes.uv.array;
 
 		const faceTris = positions.length / 6;
+		const faceDirVector = new Vector3();
 
 		for ( let i = 0, j = 0; i < positions.length; i += 3, j += 2 ) {
 
@@ -47,28 +82,51 @@ class RoundedBoxBufferGeometry extends BoxBufferGeometry {
 			switch ( side ) {
 
 				case 0: // right
-					uvs[ j + 0 ] = 0.5 - ( positions[ i + 2 ] / ( depth - radius ) );
-					uvs[ j + 1 ] = 0.5 + ( positions[ i + 1 ] / ( height - radius ) );
+
+					// generate UVs along Z then Y
+					faceDirVector.set( 1, 0, 0 );
+					uvs[ j + 0 ] = getUv( faceDirVector, normal, 'z', 'y', radius, depth );
+					uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'z', radius, height );
 					break;
+
 				case 1: // left
-					uvs[ j + 0 ] = 0.5 + ( positions[ i + 2 ] / ( depth - radius ) );
-					uvs[ j + 1 ] = 0.5 + ( positions[ i + 1 ] / ( height - radius ) );
+
+					// generate UVs along Z then Y
+					faceDirVector.set( - 1, 0, 0 );
+					uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'z', 'y', radius, depth );
+					uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'z', radius, height );
 					break;
+
 				case 2: // top
-					uvs[ j + 0 ] = 0.5 + ( positions[ i + 0 ] / ( width - radius ) );
-					uvs[ j + 1 ] = 0.5 - ( positions[ i + 2 ] / ( depth - radius ) );
+
+					// generate UVs along X then Z
+					faceDirVector.set( 0, 1, 0 );
+					uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'x', 'z', radius, width );
+					uvs[ j + 1 ] = getUv( faceDirVector, normal, 'z', 'x', radius, depth );
 					break;
+
 				case 3: // bottom
-					uvs[ j + 0 ] = 0.5 + ( positions[ i + 0 ] / ( width - radius ) );
-					uvs[ j + 1 ] = 0.5 + ( positions[ i + 2 ] / ( depth - radius ) );
+
+					// generate UVs along X then Z
+					faceDirVector.set( 0, -1, 0 );
+					uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'x', 'z', radius, width );
+					uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'z', 'x', radius, depth );
 					break;
+
 				case 4: // front
-					uvs[ j + 0 ] = 0.5 + ( positions[ i + 0 ] / ( width - radius ) );
-					uvs[ j + 1 ] = 0.5 + ( positions[ i + 1 ] / ( height - radius ) );
+
+					// generate UVs along X then Y
+					faceDirVector.set( 0, 0, 1 );
+					uvs[ j + 0 ] = 1.0 - getUv( faceDirVector, normal, 'x', 'y', radius, width );
+					uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'x', radius, height );
 					break;
+
 				case 5: // back
-					uvs[ j + 0 ] = 0.5 - ( positions[ i + 0 ] / ( width - radius ) );
-					uvs[ j + 1 ] = 0.5 + ( positions[ i + 1 ] / ( height - radius ) );
+
+					// generate UVs along X then Y
+					faceDirVector.set( 0, 0, - 1 );
+					uvs[ j + 0 ] = getUv( faceDirVector, normal, 'x', 'y', radius, width );
+					uvs[ j + 1 ] = 1.0 - getUv( faceDirVector, normal, 'y', 'x', radius, height );
 					break;
 
 			}