diff --git a/editor/js/Loader.js b/editor/js/Loader.js index 5d6e70847c6181..7b62f314e339da 100644 --- a/editor/js/Loader.js +++ b/editor/js/Loader.js @@ -780,7 +780,7 @@ function Loader( editor ) { const { USDLoader } = await import( 'three/addons/loaders/USDLoader.js' ); const loader = new USDLoader( manager ); - loader.parse( contents, function ( group ) { + loader.parse( contents, '', function ( group ) { group.name = filename; editor.execute( new AddObjectCommand( editor, group ) ); diff --git a/examples/jsm/lines/LineMaterial.js b/examples/jsm/lines/LineMaterial.js index 856bb8f499ffc5..c7e1684e11bf09 100644 --- a/examples/jsm/lines/LineMaterial.js +++ b/examples/jsm/lines/LineMaterial.js @@ -70,21 +70,20 @@ ShaderLib[ 'line' ] = { #endif - void trimSegment( const in vec4 start, inout vec4 end ) { + float trimSegmentAlpha( const in vec4 start, const in vec4 end ) { - // trim end segment so it terminates between the camera plane and the near plane + // compute the interpolation factor needed to trim the segment so it terminates + // between the camera plane and the near plane // conservative estimate of the near plane float a = projectionMatrix[ 2 ][ 2 ]; // 3nd entry in 3th column float b = projectionMatrix[ 3 ][ 2 ]; // 3nd entry in 4th column - + // we need different nearEstimate formula for reversed and default depth buffer // a is positive with a reversed depth buffer so it can be used for controlling the code flow float nearEstimate = ( a > 0.0 ) ? ( - b / ( a + 1.0 ) ) : ( - 0.5 * b / a ); - float alpha = ( nearEstimate - start.z ) / ( end.z - start.z ); - - end.xyz = mix( start.xyz, end.xyz, alpha ); + return ( nearEstimate - start.z ) / ( end.z - start.z ); } @@ -96,19 +95,19 @@ ShaderLib[ 'line' ] = { #endif - #ifdef USE_DASH - - vLineDistance = ( position.y < 0.5 ) ? dashScale * instanceDistanceStart : dashScale * instanceDistanceEnd; - vUv = uv; - - #endif - float aspect = resolution.x / resolution.y; // camera space vec4 start = modelViewMatrix * vec4( instanceStart, 1.0 ); vec4 end = modelViewMatrix * vec4( instanceEnd, 1.0 ); + #ifdef USE_DASH + + float lineDistanceStart = dashScale * instanceDistanceStart; + float lineDistanceEnd = dashScale * instanceDistanceEnd; + + #endif + #ifdef WORLD_UNITS worldStart = start.xyz; @@ -131,16 +130,37 @@ ShaderLib[ 'line' ] = { if ( start.z < 0.0 && end.z >= 0.0 ) { - trimSegment( start, end ); + float alpha = trimSegmentAlpha( start, end ); + end.xyz = mix( start.xyz, end.xyz, alpha ); + + #ifdef USE_DASH + + lineDistanceEnd = mix( lineDistanceStart, lineDistanceEnd, alpha ); + + #endif } else if ( end.z < 0.0 && start.z >= 0.0 ) { - trimSegment( end, start ); + float alpha = trimSegmentAlpha( end, start ); + start.xyz = mix( end.xyz, start.xyz, alpha ); + + #ifdef USE_DASH + + lineDistanceStart = mix( lineDistanceEnd, lineDistanceStart, alpha ); + + #endif } } + #ifdef USE_DASH + + vLineDistance = ( position.y < 0.5 ) ? lineDistanceStart : lineDistanceEnd; + vUv = uv; + + #endif + // clip space vec4 clipStart = projectionMatrix * start; vec4 clipEnd = projectionMatrix * end; diff --git a/examples/jsm/loaders/USDLoader.js b/examples/jsm/loaders/USDLoader.js index b7536a59d22c00..6b1ff7ccf76789 100644 --- a/examples/jsm/loaders/USDLoader.js +++ b/examples/jsm/loaders/USDLoader.js @@ -1,6 +1,7 @@ import { FileLoader, - Loader + Loader, + LoaderUtils } from 'three'; import { unzipSync } from '../libs/fflate.module.js'; @@ -49,6 +50,8 @@ class USDLoader extends Loader { const scope = this; + const path = ( scope.path === '' ) ? LoaderUtils.extractUrlBase( url ) : scope.path; + const loader = new FileLoader( scope.manager ); loader.setPath( scope.path ); loader.setResponseType( 'arraybuffer' ); @@ -58,7 +61,7 @@ class USDLoader extends Loader { try { - scope.parse( text, onLoad, onError ); + scope.parse( text, path, onLoad, onError ); } catch ( e ) { @@ -88,11 +91,12 @@ class USDLoader extends Loader { * textures have finished loading. * * @param {ArrayBuffer|string} buffer - The raw USDZ data as an array buffer. + * @param {string} [path=''] - The URL base path. * @param {function(Group)} [onLoad] - Executed once the group and all of its textures are ready. * @param {onErrorCallback} [onError] - Executed when errors occur. * @return {Group} The parsed asset as a group. */ - parse( buffer, onLoad, onError ) { + parse( buffer, path = '', onLoad, onError ) { const usda = new USDAParser(); const usdc = new USDCParser(); @@ -243,7 +247,7 @@ class USDLoader extends Loader { const composer = new USDComposer( scope.manager ); const data = usda.parseData( buffer ); - return finalize( composer, composer.compose( data, {} ) ); + return finalize( composer, composer.compose( data, {}, {}, path ) ); } @@ -253,7 +257,7 @@ class USDLoader extends Loader { const composer = new USDComposer( scope.manager ); const data = usdc.parseData( toArrayBuffer( buffer ) ); - return finalize( composer, composer.compose( data, {} ) ); + return finalize( composer, composer.compose( data, {}, {}, path ) ); } @@ -290,7 +294,7 @@ class USDLoader extends Loader { const composer = new USDComposer( scope.manager ); const text = textDecoder.decode( bytes ); const data = usda.parseData( text ); - return finalize( composer, composer.compose( data, {} ) ); + return finalize( composer, composer.compose( data, {}, {}, path ) ); } diff --git a/examples/jsm/loaders/usd/USDComposer.js b/examples/jsm/loaders/usd/USDComposer.js index 4dbc5adb881b3a..5de046b2ab54aa 100644 --- a/examples/jsm/loaders/usd/USDComposer.js +++ b/examples/jsm/loaders/usd/USDComposer.js @@ -11,6 +11,7 @@ import { DirectionalLight, Euler, Group, + LoaderUtils, Matrix4, Mesh, MeshPhysicalMaterial, @@ -854,14 +855,13 @@ class USDComposer { } - // Combine with base path - if ( this.basePath ) { + if ( ! this.basePath ) return cleanPath; - return this.basePath + '/' + cleanPath; + // LoaderUtils.resolveURL expects basePath to end with a separator; + // the USDZ flow passes the zip-internal directory name without one. + const base = this.basePath.endsWith( '/' ) ? this.basePath : this.basePath + '/'; - } - - return cleanPath; + return LoaderUtils.resolveURL( cleanPath, base ); } @@ -3819,6 +3819,16 @@ class USDComposer { } + // Standalone .usd/.usda/.usdc files don't pre-load assets; treat the + // resolved path as a URL relative to basePath so the browser fetches + // the texture from disk next to the layer. + + if ( this.basePath ) { + + return this._createTextureFromData( resolvedPath, textureAttrs, transformAttrs ); + + } + // Try loading via LoadingManager if available if ( this.manager ) { diff --git a/src/materials/nodes/Line2NodeMaterial.js b/src/materials/nodes/Line2NodeMaterial.js index 65d1cd0a911a5d..4d4db8c9d66ebc 100644 --- a/src/materials/nodes/Line2NodeMaterial.js +++ b/src/materials/nodes/Line2NodeMaterial.js @@ -137,7 +137,7 @@ class Line2NodeMaterial extends NodeMaterial { const useDash = this._useDash; const useWorldUnits = this._useWorldUnits; - const trimSegment = Fn( ( { start, end } ) => { + const trimSegmentAlpha = Fn( ( { start, end } ) => { const a = cameraProjectionMatrix.element( 2 ).element( 2 ); // 3nd entry in 3th column const b = cameraProjectionMatrix.element( 3 ).element( 2 ); // 3nd entry in 4th column @@ -147,13 +147,11 @@ class Line2NodeMaterial extends NodeMaterial { const nearEstimate = a.greaterThan( 0 ).select( b.negate().div( a.add( 1 ) ), b.mul( - 0.5 ).div( a ) ); - const alpha = nearEstimate.sub( start.z ).div( end.z.sub( start.z ) ); - - return vec4( mix( start.xyz, end.xyz, alpha ), end.w ); + return nearEstimate.sub( start.z ).div( end.z.sub( start.z ) ); } ).setLayout( { - name: 'trimSegment', - type: 'vec4', + name: 'trimSegmentAlpha', + type: 'float', inputs: [ { name: 'start', type: 'vec4' }, { name: 'end', type: 'vec4' } @@ -170,18 +168,12 @@ class Line2NodeMaterial extends NodeMaterial { const start = vec4( modelViewMatrix.mul( vec4( instanceStart, 1.0 ) ) ).toVar( 'start' ); const end = vec4( modelViewMatrix.mul( vec4( instanceEnd, 1.0 ) ) ).toVar( 'end' ); - if ( useDash ) { - - const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; - const offsetNode = this.offsetNode ? float( this.offsetNode ) : materialLineDashOffset; - - const instanceDistanceStart = attribute( 'instanceDistanceStart' ); - const instanceDistanceEnd = attribute( 'instanceDistanceEnd' ); + let distanceStart, distanceEnd; - let lineDistance = positionGeometry.y.lessThan( 0.5 ).select( dashScaleNode.mul( instanceDistanceStart ), dashScaleNode.mul( instanceDistanceEnd ) ); - lineDistance = lineDistance.add( offsetNode ); + if ( useDash ) { - varyingProperty( 'float', 'lineDistance' ).assign( lineDistance ); + distanceStart = float( attribute( 'instanceDistanceStart' ) ).toVar( 'distanceStart' ); + distanceEnd = float( attribute( 'instanceDistanceEnd' ) ).toVar( 'distanceEnd' ); } @@ -205,16 +197,42 @@ class Line2NodeMaterial extends NodeMaterial { If( start.z.lessThan( 0.0 ).and( end.z.greaterThan( 0.0 ) ), () => { - end.assign( trimSegment( { start: start, end: end } ) ); + const alpha = trimSegmentAlpha( { start: start, end: end } ); + end.assign( vec4( mix( start.xyz, end.xyz, alpha ), end.w ) ); + + if ( useDash ) { + + distanceEnd.assign( mix( distanceStart, distanceEnd, alpha ) ); + + } } ).ElseIf( end.z.lessThan( 0.0 ).and( start.z.greaterThanEqual( 0.0 ) ), () => { - start.assign( trimSegment( { start: end, end: start } ) ); + const alpha = trimSegmentAlpha( { start: end, end: start } ); + start.assign( vec4( mix( end.xyz, start.xyz, alpha ), start.w ) ); + + if ( useDash ) { + + distanceStart.assign( mix( distanceEnd, distanceStart, alpha ) ); + + } } ); } ); + if ( useDash ) { + + const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; + const offsetNode = this.offsetNode ? float( this.offsetNode ) : materialLineDashOffset; + + let lineDistance = positionGeometry.y.lessThan( 0.5 ).select( dashScaleNode.mul( distanceStart ), dashScaleNode.mul( distanceEnd ) ); + lineDistance = lineDistance.add( offsetNode ); + + varyingProperty( 'float', 'lineDistance' ).assign( lineDistance ); + + } + // clip space const clipStart = cameraProjectionMatrix.mul( start ); const clipEnd = cameraProjectionMatrix.mul( end ); @@ -341,6 +359,15 @@ class Line2NodeMaterial extends NodeMaterial { return vec2( mua, mub ); + } ).setLayout( { + name: 'closestLineToLine', + type: 'vec2', + inputs: [ + { name: 'p1', type: 'vec3' }, + { name: 'p2', type: 'vec3' }, + { name: 'p3', type: 'vec3' }, + { name: 'p4', type: 'vec3' } + ] } ); this.colorNode = Fn( () => {