| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 | import {	Vector2} from '../../../build/three.module.js';/** * tool for "unwrapping" and debugging three.js geometries UV mapping * * Sample usage: *	document.body.appendChild( UVsDebug( new THREE.SphereGeometry( 10, 10, 10, 10 ) ); * */function UVsDebug( geometry, size = 1024 ) {	// handles wrapping of uv.x > 1 only	const abc = 'abc';	const a = new Vector2();	const b = new Vector2();	const uvs = [		new Vector2(),		new Vector2(),		new Vector2()	];	const face = [];	const canvas = document.createElement( 'canvas' );	const width = size; // power of 2 required for wrapping	const height = size;	canvas.width = width;	canvas.height = height;	const ctx = canvas.getContext( '2d' );	ctx.lineWidth = 1;	ctx.strokeStyle = 'rgb( 63, 63, 63 )';	ctx.textAlign = 'center';	// paint background white	ctx.fillStyle = 'rgb( 255, 255, 255 )';	ctx.fillRect( 0, 0, width, height );	if ( geometry.isGeometry ) {		console.error( 'THREE.UVsDebug no longer supports Geometry. Use THREE.BufferGeometry instead.' );		return;	} else {		const index = geometry.index;		const uvAttribute = geometry.attributes.uv;		if ( index ) {			// indexed geometry			for ( let i = 0, il = index.count; i < il; i += 3 ) {				face[ 0 ] = index.getX( i );				face[ 1 ] = index.getX( i + 1 );				face[ 2 ] = index.getX( i + 2 );				uvs[ 0 ].fromBufferAttribute( uvAttribute, face[ 0 ] );				uvs[ 1 ].fromBufferAttribute( uvAttribute, face[ 1 ] );				uvs[ 2 ].fromBufferAttribute( uvAttribute, face[ 2 ] );				processFace( face, uvs, i / 3 );			}		} else {			// non-indexed geometry			for ( let i = 0, il = uvAttribute.count; i < il; i += 3 ) {				face[ 0 ] = i;				face[ 1 ] = i + 1;				face[ 2 ] = i + 2;				uvs[ 0 ].fromBufferAttribute( uvAttribute, face[ 0 ] );				uvs[ 1 ].fromBufferAttribute( uvAttribute, face[ 1 ] );				uvs[ 2 ].fromBufferAttribute( uvAttribute, face[ 2 ] );				processFace( face, uvs, i / 3 );			}		}	}	return canvas;	function processFace( face, uvs, index ) {		// draw contour of face		ctx.beginPath();		a.set( 0, 0 );		for ( let j = 0, jl = uvs.length; j < jl; j ++ ) {			const uv = uvs[ j ];			a.x += uv.x;			a.y += uv.y;			if ( j === 0 ) {				ctx.moveTo( uv.x * ( width - 2 ) + 0.5, ( 1 - uv.y ) * ( height - 2 ) + 0.5 );			} else {				ctx.lineTo( uv.x * ( width - 2 ) + 0.5, ( 1 - uv.y ) * ( height - 2 ) + 0.5 );			}		}		ctx.closePath();		ctx.stroke();		// calculate center of face		a.divideScalar( uvs.length );		// label the face number		ctx.font = '18px Arial';		ctx.fillStyle = 'rgb( 63, 63, 63 )';		ctx.fillText( index, a.x * width, ( 1 - a.y ) * height );		if ( a.x > 0.95 ) {			// wrap x // 0.95 is arbitrary			ctx.fillText( index, ( a.x % 1 ) * width, ( 1 - a.y ) * height );		}		//		ctx.font = '12px Arial';		ctx.fillStyle = 'rgb( 191, 191, 191 )';		// label uv edge orders		for ( let j = 0, jl = uvs.length; j < jl; j ++ ) {			const uv = uvs[ j ];			b.addVectors( a, uv ).divideScalar( 2 );			const vnum = face[ j ];			ctx.fillText( abc[ j ] + vnum, b.x * width, ( 1 - b.y ) * height );			if ( b.x > 0.95 ) {				// wrap x				ctx.fillText( abc[ j ] + vnum, ( b.x % 1 ) * width, ( 1 - b.y ) * height );			}		}	}}export { UVsDebug };
 |