@plastic-software/three 0.178.0 → 0.179.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/build/three.cjs +856 -196
- package/build/three.core.js +647 -123
- package/build/three.core.min.js +1 -1
- package/build/three.module.js +211 -76
- package/build/three.module.min.js +1 -1
- package/build/three.tsl.js +70 -21
- package/build/three.tsl.min.js +1 -1
- package/build/three.webgpu.js +1796 -557
- package/build/three.webgpu.min.js +1 -1
- package/build/three.webgpu.nodes.js +1754 -557
- package/build/three.webgpu.nodes.min.js +1 -1
- package/examples/jsm/Addons.js +1 -2
- package/examples/jsm/capabilities/WebGPU.js +1 -1
- package/examples/jsm/csm/CSMShadowNode.js +4 -4
- package/examples/jsm/environments/RoomEnvironment.js +8 -3
- package/examples/jsm/exporters/USDZExporter.js +676 -299
- package/examples/jsm/geometries/RoundedBoxGeometry.js +47 -8
- package/examples/jsm/interactive/HTMLMesh.js +5 -3
- package/examples/jsm/libs/meshopt_decoder.module.js +75 -58
- package/examples/jsm/lights/LightProbeGenerator.js +14 -3
- package/examples/jsm/loaders/EXRLoader.js +210 -22
- package/examples/jsm/loaders/FBXLoader.js +1 -1
- package/examples/jsm/loaders/MaterialXLoader.js +212 -30
- package/examples/jsm/loaders/TTFLoader.js +13 -1
- package/examples/jsm/loaders/USDLoader.js +219 -0
- package/examples/jsm/loaders/USDZLoader.js +4 -892
- package/examples/jsm/loaders/usd/USDAParser.js +741 -0
- package/examples/jsm/loaders/usd/USDCParser.js +17 -0
- package/examples/jsm/objects/LensflareMesh.js +3 -3
- package/examples/jsm/objects/SkyMesh.js +2 -2
- package/examples/jsm/physics/RapierPhysics.js +14 -5
- package/examples/jsm/postprocessing/GTAOPass.js +10 -9
- package/examples/jsm/postprocessing/OutlinePass.js +17 -17
- package/examples/jsm/postprocessing/SSAOPass.js +10 -9
- package/examples/jsm/shaders/UnpackDepthRGBAShader.js +11 -2
- package/examples/jsm/transpiler/GLSLDecoder.js +2 -2
- package/examples/jsm/tsl/display/BloomNode.js +8 -7
- package/examples/jsm/tsl/display/GaussianBlurNode.js +6 -8
- package/examples/jsm/tsl/display/{TRAAPassNode.js → TRAANode.js} +181 -172
- package/examples/jsm/tsl/lighting/TiledLightsNode.js +1 -1
- package/package.json +1 -1
- package/src/Three.Core.js +1 -0
- package/src/Three.TSL.js +69 -20
- package/src/animation/KeyframeTrack.js +1 -1
- package/src/animation/tracks/BooleanKeyframeTrack.js +1 -1
- package/src/animation/tracks/StringKeyframeTrack.js +1 -1
- package/src/cameras/Camera.js +14 -0
- package/src/cameras/OrthographicCamera.js +1 -1
- package/src/cameras/PerspectiveCamera.js +1 -1
- package/src/constants.js +1 -1
- package/{examples/jsm/misc → src/core}/Timer.js +4 -42
- package/src/extras/PMREMGenerator.js +11 -0
- package/src/helpers/CameraHelper.js +41 -11
- package/src/helpers/SkeletonHelper.js +35 -6
- package/src/lights/LightShadow.js +21 -8
- package/src/lights/PointLightShadow.js +1 -1
- package/src/loaders/FileLoader.js +25 -2
- package/src/loaders/ImageBitmapLoader.js +23 -0
- package/src/loaders/Loader.js +14 -0
- package/src/loaders/LoadingManager.js +23 -0
- package/src/materials/MeshBasicMaterial.js +1 -1
- package/src/materials/nodes/Line2NodeMaterial.js +0 -8
- package/src/materials/nodes/NodeMaterial.js +1 -1
- package/src/materials/nodes/PointsNodeMaterial.js +5 -0
- package/src/materials/nodes/manager/NodeMaterialObserver.js +87 -2
- package/src/math/Frustum.js +19 -8
- package/src/math/FrustumArray.js +10 -5
- package/src/math/Line3.js +129 -2
- package/src/math/Matrix4.js +48 -27
- package/src/math/Spherical.js +2 -2
- package/src/nodes/Nodes.js +1 -0
- package/src/nodes/TSL.js +1 -0
- package/src/nodes/accessors/Camera.js +12 -12
- package/src/nodes/accessors/Normal.js +11 -11
- package/src/nodes/accessors/ReferenceNode.js +18 -3
- package/src/nodes/accessors/SceneNode.js +1 -1
- package/src/nodes/accessors/StorageTextureNode.js +1 -1
- package/src/nodes/accessors/TextureNode.js +12 -0
- package/src/nodes/core/ArrayNode.js +12 -0
- package/src/nodes/core/AssignNode.js +3 -0
- package/src/nodes/core/ContextNode.js +20 -1
- package/src/nodes/core/Node.js +14 -2
- package/src/nodes/core/NodeBuilder.js +25 -20
- package/src/nodes/core/NodeUtils.js +4 -1
- package/src/nodes/core/StackNode.js +42 -0
- package/src/nodes/core/UniformNode.js +63 -5
- package/src/nodes/core/VarNode.js +91 -2
- package/src/nodes/display/PassNode.js +148 -2
- package/src/nodes/display/ViewportTextureNode.js +67 -7
- package/src/nodes/functions/PhysicalLightingModel.js +2 -2
- package/src/nodes/gpgpu/AtomicFunctionNode.js +1 -1
- package/src/nodes/gpgpu/ComputeNode.js +67 -23
- package/src/nodes/gpgpu/WorkgroupInfoNode.js +28 -3
- package/src/nodes/lighting/ProjectorLightNode.js +19 -6
- package/src/nodes/lighting/ShadowFilterNode.js +1 -1
- package/src/nodes/materialx/MaterialXNodes.js +131 -2
- package/src/nodes/materialx/lib/mx_noise.js +165 -1
- package/src/nodes/math/ConditionalNode.js +1 -1
- package/src/nodes/math/MathNode.js +78 -54
- package/src/nodes/math/OperatorNode.js +22 -22
- package/src/nodes/tsl/TSLCore.js +64 -9
- package/src/nodes/utils/DebugNode.js +1 -1
- package/src/nodes/utils/EventNode.js +83 -0
- package/src/nodes/utils/RTTNode.js +9 -0
- package/src/objects/BatchedMesh.js +4 -2
- package/src/renderers/WebGLRenderer.js +21 -22
- package/src/renderers/common/Bindings.js +19 -18
- package/src/renderers/common/Color4.js +2 -2
- package/src/renderers/common/PostProcessing.js +60 -5
- package/src/renderers/common/Renderer.js +18 -15
- package/src/renderers/common/SampledTexture.js +3 -71
- package/src/renderers/common/Sampler.js +79 -0
- package/src/renderers/common/Storage3DTexture.js +21 -0
- package/src/renderers/common/StorageArrayTexture.js +21 -0
- package/src/renderers/common/StorageTexture.js +19 -0
- package/src/renderers/common/Textures.js +19 -3
- package/src/renderers/common/XRManager.js +26 -8
- package/src/renderers/common/nodes/NodeSampledTexture.js +0 -12
- package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +20 -2
- package/src/renderers/shaders/ShaderLib/depth.glsl.js +11 -2
- package/src/renderers/webgl/WebGLCapabilities.js +2 -2
- package/src/renderers/webgl/WebGLMaterials.js +6 -6
- package/src/renderers/webgl/WebGLProgram.js +22 -16
- package/src/renderers/webgl/WebGLPrograms.js +4 -4
- package/src/renderers/webgl/WebGLShadowMap.js +11 -1
- package/src/renderers/webgl/WebGLTextures.js +19 -7
- package/src/renderers/webgl-fallback/WebGLBackend.js +22 -12
- package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +2 -2
- package/src/renderers/webgpu/WebGPUBackend.js +54 -15
- package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +53 -73
- package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +35 -31
- package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +1 -1
- package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +11 -64
- package/src/renderers/webgpu/utils/WebGPUUtils.js +2 -17
- package/src/renderers/webxr/WebXRDepthSensing.js +6 -10
- package/src/renderers/webxr/WebXRManager.js +68 -8
- package/src/textures/ExternalTexture.js +45 -0
- package/src/textures/FramebufferTexture.js +2 -2
- package/src/textures/Source.js +11 -1
- package/src/textures/VideoTexture.js +30 -2
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
FileLoader, Loader, TextureLoader, RepeatWrapping, MeshBasicNodeMaterial,
|
|
3
|
+
MeshPhysicalNodeMaterial, DoubleSide,
|
|
4
|
+
} from 'three/webgpu';
|
|
2
5
|
|
|
3
6
|
import {
|
|
4
7
|
float, bool, int, vec2, vec3, vec4, color, texture,
|
|
5
8
|
positionLocal, positionWorld, uv, vertexColor,
|
|
6
9
|
normalLocal, normalWorld, tangentLocal, tangentWorld,
|
|
7
|
-
|
|
8
|
-
asin, acos,
|
|
10
|
+
mul, abs, sign, floor, ceil, round, sin, cos, tan,
|
|
11
|
+
asin, acos, sqrt, exp, clamp, min, max, normalize, length, dot, cross, normalMap,
|
|
9
12
|
remap, smoothstep, luminance, mx_rgbtohsv, mx_hsvtorgb,
|
|
10
|
-
mix,
|
|
13
|
+
mix, saturation, transpose, determinant, inverse, log, reflect, refract, element,
|
|
11
14
|
mx_ramplr, mx_ramptb, mx_splitlr, mx_splittb,
|
|
12
15
|
mx_fractal_noise_float, mx_noise_float, mx_cell_noise_float, mx_worley_noise_float,
|
|
13
16
|
mx_transform_uv,
|
|
14
17
|
mx_safepower, mx_contrast,
|
|
15
18
|
mx_srgb_texture_to_lin_rec709,
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
mx_add, mx_atan2, mx_divide, mx_modulo, mx_multiply, mx_power, mx_subtract,
|
|
20
|
+
mx_timer, mx_frame, mat3, mx_ramp4,
|
|
21
|
+
mx_invert, mx_ifgreater, mx_ifgreatereq, mx_ifequal, distance,
|
|
22
|
+
mx_separate, mx_place2d, mx_rotate2d, mx_rotate3d, mx_heighttonormal,
|
|
23
|
+
mx_unifiednoise2d, mx_unifiednoise3d
|
|
18
24
|
} from 'three/tsl';
|
|
19
25
|
|
|
20
26
|
const colorSpaceLib = {
|
|
@@ -35,19 +41,9 @@ class MXElement {
|
|
|
35
41
|
|
|
36
42
|
// Ref: https://github.com/mrdoob/three.js/issues/24674
|
|
37
43
|
|
|
38
|
-
|
|
39
|
-
const mx_subtract = ( in1, in2 = float( 0 ) ) => sub( in1, in2 );
|
|
40
|
-
const mx_multiply = ( in1, in2 = float( 1 ) ) => mul( in1, in2 );
|
|
41
|
-
const mx_divide = ( in1, in2 = float( 1 ) ) => div( in1, in2 );
|
|
42
|
-
const mx_modulo = ( in1, in2 = float( 1 ) ) => mod( in1, in2 );
|
|
43
|
-
const mx_power = ( in1, in2 = float( 1 ) ) => pow( in1, in2 );
|
|
44
|
-
const mx_atan2 = ( in1 = float( 0 ), in2 = float( 1 ) ) => atan2( in1, in2 );
|
|
45
|
-
const mx_timer = () => timerLocal();
|
|
46
|
-
const mx_frame = () => frameId;
|
|
47
|
-
const mx_invert = ( in1, amount = float( 1 ) ) => sub( amount, in1 );
|
|
44
|
+
// Enhanced separate node to support multi-output referencing (outx, outy, outz, outw)
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
const extract = ( in1, index ) => in1.element( index );
|
|
46
|
+
// Type/arity-aware MaterialX node wrappers
|
|
51
47
|
|
|
52
48
|
const MXElements = [
|
|
53
49
|
|
|
@@ -70,7 +66,7 @@ const MXElements = [
|
|
|
70
66
|
new MXElement( 'acos', acos, [ 'in' ] ),
|
|
71
67
|
new MXElement( 'atan2', mx_atan2, [ 'in1', 'in2' ] ),
|
|
72
68
|
new MXElement( 'sqrt', sqrt, [ 'in' ] ),
|
|
73
|
-
|
|
69
|
+
new MXElement( 'ln', log, [ 'in' ] ),
|
|
74
70
|
new MXElement( 'exp', exp, [ 'in' ] ),
|
|
75
71
|
new MXElement( 'clamp', clamp, [ 'in', 'low', 'high' ] ),
|
|
76
72
|
new MXElement( 'min', min, [ 'in1', 'in2' ] ),
|
|
@@ -79,20 +75,27 @@ const MXElements = [
|
|
|
79
75
|
new MXElement( 'magnitude', length, [ 'in1', 'in2' ] ),
|
|
80
76
|
new MXElement( 'dotproduct', dot, [ 'in1', 'in2' ] ),
|
|
81
77
|
new MXElement( 'crossproduct', cross, [ 'in' ] ),
|
|
78
|
+
new MXElement( 'distance', distance, [ 'in1', 'in2' ] ),
|
|
82
79
|
new MXElement( 'invert', mx_invert, [ 'in', 'amount' ] ),
|
|
83
80
|
//new MtlXElement( 'transformpoint', ... ),
|
|
84
81
|
//new MtlXElement( 'transformvector', ... ),
|
|
85
82
|
//new MtlXElement( 'transformnormal', ... ),
|
|
86
|
-
|
|
83
|
+
new MXElement( 'transformmatrix', mul, [ 'in1', 'in2' ] ),
|
|
87
84
|
new MXElement( 'normalmap', normalMap, [ 'in', 'scale' ] ),
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
new MXElement( 'transpose', transpose, [ 'in' ] ),
|
|
86
|
+
new MXElement( 'determinant', determinant, [ 'in' ] ),
|
|
87
|
+
new MXElement( 'invertmatrix', inverse, [ 'in' ] ),
|
|
88
|
+
new MXElement( 'creatematrix', mat3, [ 'in1', 'in2', 'in3' ] ),
|
|
91
89
|
//new MtlXElement( 'rotate2d', rotateUV, [ 'in', radians( 'amount' )** ] ),
|
|
92
90
|
//new MtlXElement( 'rotate3d', ... ),
|
|
93
91
|
//new MtlXElement( 'arrayappend', ... ),
|
|
94
92
|
//new MtlXElement( 'dot', ... ),
|
|
95
93
|
|
|
94
|
+
new MXElement( 'length', length, [ 'in' ] ),
|
|
95
|
+
new MXElement( 'crossproduct', cross, [ 'in1', 'in2' ] ),
|
|
96
|
+
new MXElement( 'floor', floor, [ 'in' ] ),
|
|
97
|
+
new MXElement( 'ceil', ceil, [ 'in' ] ),
|
|
98
|
+
|
|
96
99
|
// << Adjustment >>
|
|
97
100
|
new MXElement( 'remap', remap, [ 'in', 'inlow', 'inhigh', 'outlow', 'outhigh' ] ),
|
|
98
101
|
new MXElement( 'smoothstep', smoothstep, [ 'in', 'low', 'high' ] ),
|
|
@@ -113,6 +116,7 @@ const MXElements = [
|
|
|
113
116
|
// << Procedural >>
|
|
114
117
|
new MXElement( 'ramplr', mx_ramplr, [ 'valuel', 'valuer', 'texcoord' ] ),
|
|
115
118
|
new MXElement( 'ramptb', mx_ramptb, [ 'valuet', 'valueb', 'texcoord' ] ),
|
|
119
|
+
new MXElement( 'ramp4', mx_ramp4, [ 'valuetl', 'valuetr', 'valuebl', 'valuebr', 'texcoord' ] ),
|
|
116
120
|
new MXElement( 'splitlr', mx_splitlr, [ 'valuel', 'valuer', 'texcoord' ] ),
|
|
117
121
|
new MXElement( 'splittb', mx_splittb, [ 'valuet', 'valueb', 'texcoord' ] ),
|
|
118
122
|
new MXElement( 'noise2d', mx_noise_float, [ 'texcoord', 'amplitude', 'pivot' ] ),
|
|
@@ -122,23 +126,34 @@ const MXElements = [
|
|
|
122
126
|
new MXElement( 'cellnoise3d', mx_cell_noise_float, [ 'texcoord' ] ),
|
|
123
127
|
new MXElement( 'worleynoise2d', mx_worley_noise_float, [ 'texcoord', 'jitter' ] ),
|
|
124
128
|
new MXElement( 'worleynoise3d', mx_worley_noise_float, [ 'texcoord', 'jitter' ] ),
|
|
125
|
-
|
|
129
|
+
new MXElement( 'unifiednoise2d', mx_unifiednoise2d, [ 'type', 'texcoord', 'freq', 'offset', 'jitter', 'outmin', 'outmax', 'clampoutput', 'octaves', 'lacunarity', 'diminish' ] ),
|
|
130
|
+
new MXElement( 'unifiednoise3d', mx_unifiednoise3d, [ 'type', 'texcoord', 'freq', 'offset', 'jitter', 'outmin', 'outmax', 'clampoutput', 'octaves', 'lacunarity', 'diminish' ] ),
|
|
126
131
|
// << Supplemental >>
|
|
127
132
|
//new MtlXElement( 'tiledimage', ... ),
|
|
128
133
|
//new MtlXElement( 'triplanarprojection', triplanarTextures, [ 'filex', 'filey', 'filez' ] ),
|
|
129
134
|
//new MtlXElement( 'ramp4', ... ),
|
|
130
|
-
|
|
135
|
+
new MXElement( 'place2d', mx_place2d, [ 'texcoord', 'pivot', 'scale', 'rotate', 'offset', 'operationorder' ] ),
|
|
131
136
|
new MXElement( 'safepower', mx_safepower, [ 'in1', 'in2' ] ),
|
|
132
137
|
new MXElement( 'contrast', mx_contrast, [ 'in', 'amount', 'pivot' ] ),
|
|
133
138
|
//new MtlXElement( 'hsvadjust', ... ),
|
|
134
139
|
new MXElement( 'saturate', saturation, [ 'in', 'amount' ] ),
|
|
135
|
-
new MXElement( 'extract',
|
|
136
|
-
new MXElement( 'separate2',
|
|
137
|
-
new MXElement( 'separate3',
|
|
138
|
-
new MXElement( 'separate4',
|
|
140
|
+
new MXElement( 'extract', element, [ 'in', 'index' ] ),
|
|
141
|
+
new MXElement( 'separate2', mx_separate, [ 'in' ] ),
|
|
142
|
+
new MXElement( 'separate3', mx_separate, [ 'in' ] ),
|
|
143
|
+
new MXElement( 'separate4', mx_separate, [ 'in' ] ),
|
|
144
|
+
new MXElement( 'reflect', reflect, [ 'in', 'normal' ] ),
|
|
145
|
+
new MXElement( 'refract', refract, [ 'in', 'normal', 'ior' ] ),
|
|
139
146
|
|
|
140
147
|
new MXElement( 'time', mx_timer ),
|
|
141
|
-
new MXElement( 'frame', mx_frame )
|
|
148
|
+
new MXElement( 'frame', mx_frame ),
|
|
149
|
+
new MXElement( 'ifgreater', mx_ifgreater, [ 'value1', 'value2', 'in1', 'in2' ] ),
|
|
150
|
+
new MXElement( 'ifgreatereq', mx_ifgreatereq, [ 'value1', 'value2', 'in1', 'in2' ] ),
|
|
151
|
+
new MXElement( 'ifequal', mx_ifequal, [ 'value1', 'value2', 'in1', 'in2' ] ),
|
|
152
|
+
|
|
153
|
+
// Placeholder implementations for unsupported nodes
|
|
154
|
+
new MXElement( 'rotate2d', mx_rotate2d, [ 'in', 'amount' ] ),
|
|
155
|
+
new MXElement( 'rotate3d', mx_rotate3d, [ 'in', 'amount', 'axis' ] ),
|
|
156
|
+
new MXElement( 'heighttonormal', mx_heighttonormal, [ 'in', 'scale', 'texcoord' ] ),
|
|
142
157
|
|
|
143
158
|
];
|
|
144
159
|
|
|
@@ -220,6 +235,22 @@ class MaterialXLoader extends Loader {
|
|
|
220
235
|
/**
|
|
221
236
|
* Parses the given MaterialX data and returns the resulting materials.
|
|
222
237
|
*
|
|
238
|
+
* Supported standard_surface inputs:
|
|
239
|
+
* - base, base_color: Base color/albedo
|
|
240
|
+
* - opacity: Alpha/transparency
|
|
241
|
+
* - specular_roughness: Surface roughness
|
|
242
|
+
* - metalness: Metallic property
|
|
243
|
+
* - specular: Specular reflection intensity
|
|
244
|
+
* - specular_color: Specular reflection color
|
|
245
|
+
* - ior: Index of refraction
|
|
246
|
+
* - specular_anisotropy, specular_rotation: Anisotropic reflection
|
|
247
|
+
* - transmission, transmission_color: Transmission properties
|
|
248
|
+
* - thin_film_thickness, thin_film_ior: Thin film interference
|
|
249
|
+
* - sheen, sheen_color, sheen_roughness: Sheen properties
|
|
250
|
+
* - normal: Normal map
|
|
251
|
+
* - coat, coat_roughness, coat_color: Clearcoat properties
|
|
252
|
+
* - emission, emissionColor: Emission properties
|
|
253
|
+
*
|
|
223
254
|
* @param {string} text - The raw MaterialX data as a string.
|
|
224
255
|
* @return {Object<string,NodeMaterial>} A dictionary holding the parse node materials.
|
|
225
256
|
*/
|
|
@@ -235,6 +266,12 @@ class MaterialXNode {
|
|
|
235
266
|
|
|
236
267
|
constructor( materialX, nodeXML, nodePath = '' ) {
|
|
237
268
|
|
|
269
|
+
if ( ! materialX || typeof materialX !== 'object' ) {
|
|
270
|
+
|
|
271
|
+
console.warn( 'MaterialXNode: materialX argument is not an object!', { materialX, nodeXML, nodePath } );
|
|
272
|
+
|
|
273
|
+
}
|
|
274
|
+
|
|
238
275
|
this.materialX = materialX;
|
|
239
276
|
this.nodeXML = nodeXML;
|
|
240
277
|
this.nodePath = nodePath ? nodePath + '/' + this.name : this.name;
|
|
@@ -418,6 +455,37 @@ class MaterialXNode {
|
|
|
418
455
|
|
|
419
456
|
}
|
|
420
457
|
|
|
458
|
+
// Handle <input name="texcoord" type="vector2" ... />
|
|
459
|
+
if (
|
|
460
|
+
this.element === 'input' &&
|
|
461
|
+
this.name === 'texcoord' &&
|
|
462
|
+
this.type === 'vector2'
|
|
463
|
+
) {
|
|
464
|
+
|
|
465
|
+
// Try to get index from defaultgeomprop (e.g., "UV0" => 0)
|
|
466
|
+
let index = 0;
|
|
467
|
+
const defaultGeomProp = this.getAttribute( 'defaultgeomprop' );
|
|
468
|
+
if ( defaultGeomProp && /^UV(\d+)$/.test( defaultGeomProp ) ) {
|
|
469
|
+
|
|
470
|
+
index = parseInt( defaultGeomProp.match( /^UV(\d+)$/ )[ 1 ], 10 );
|
|
471
|
+
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
node = uv( index );
|
|
475
|
+
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Multi-output support for separate/separate3
|
|
479
|
+
if (
|
|
480
|
+
( this.element === 'separate3' || this.element === 'separate2' || this.element === 'separate4' ) &&
|
|
481
|
+
out && typeof out === 'string' && out.startsWith( 'out' )
|
|
482
|
+
) {
|
|
483
|
+
|
|
484
|
+
const inNode = this.getNodeByName( 'in' );
|
|
485
|
+
return mx_separate( inNode, out );
|
|
486
|
+
|
|
487
|
+
}
|
|
488
|
+
|
|
421
489
|
//
|
|
422
490
|
|
|
423
491
|
const type = this.type;
|
|
@@ -519,6 +587,18 @@ class MaterialXNode {
|
|
|
519
587
|
|
|
520
588
|
const nodeElement = MtlXLibrary[ element ];
|
|
521
589
|
|
|
590
|
+
if ( ! nodeElement ) {
|
|
591
|
+
|
|
592
|
+
throw new Error( `THREE.MaterialXLoader: Unexpected node ${ new XMLSerializer().serializeToString( this.nodeXML ) }.` );
|
|
593
|
+
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if ( ! nodeElement.nodeFunc ) {
|
|
597
|
+
|
|
598
|
+
throw new Error( `THREE.MaterialXLoader: Unexpected node 2 ${ new XMLSerializer().serializeToString( this.nodeXML ) }.` );
|
|
599
|
+
|
|
600
|
+
}
|
|
601
|
+
|
|
522
602
|
if ( out !== null ) {
|
|
523
603
|
|
|
524
604
|
node = nodeElement.nodeFunc( ...this.getNodesByNames( ...nodeElement.params ), out );
|
|
@@ -551,6 +631,11 @@ class MaterialXNode {
|
|
|
551
631
|
|
|
552
632
|
node = nodeToTypeClass( node );
|
|
553
633
|
|
|
634
|
+
} else {
|
|
635
|
+
|
|
636
|
+
console.warn( `THREE.MaterialXLoader: Unexpected node ${ new XMLSerializer().serializeToString( this.nodeXML ) }.` );
|
|
637
|
+
node = float( 0 );
|
|
638
|
+
|
|
554
639
|
}
|
|
555
640
|
|
|
556
641
|
node.name = this.name;
|
|
@@ -673,6 +758,12 @@ class MaterialXNode {
|
|
|
673
758
|
|
|
674
759
|
//
|
|
675
760
|
|
|
761
|
+
let opacityNode = null;
|
|
762
|
+
|
|
763
|
+
if ( inputs.opacity ) opacityNode = inputs.opacity;
|
|
764
|
+
|
|
765
|
+
//
|
|
766
|
+
|
|
676
767
|
let roughnessNode = null;
|
|
677
768
|
|
|
678
769
|
if ( inputs.specular_roughness ) roughnessNode = inputs.specular_roughness;
|
|
@@ -685,6 +776,64 @@ class MaterialXNode {
|
|
|
685
776
|
|
|
686
777
|
//
|
|
687
778
|
|
|
779
|
+
let specularIntensityNode = null;
|
|
780
|
+
|
|
781
|
+
if ( inputs.specular ) specularIntensityNode = inputs.specular;
|
|
782
|
+
|
|
783
|
+
//
|
|
784
|
+
|
|
785
|
+
let specularColorNode = null;
|
|
786
|
+
|
|
787
|
+
if ( inputs.specular_color ) specularColorNode = inputs.specular_color;
|
|
788
|
+
|
|
789
|
+
//
|
|
790
|
+
|
|
791
|
+
let iorNode = null;
|
|
792
|
+
|
|
793
|
+
if ( inputs.ior ) iorNode = inputs.ior;
|
|
794
|
+
|
|
795
|
+
//
|
|
796
|
+
|
|
797
|
+
let anisotropyNode = null;
|
|
798
|
+
let anisotropyRotationNode = null;
|
|
799
|
+
|
|
800
|
+
if ( inputs.specular_anisotropy ) anisotropyNode = inputs.specular_anisotropy;
|
|
801
|
+
if ( inputs.specular_rotation ) anisotropyRotationNode = inputs.specular_rotation;
|
|
802
|
+
|
|
803
|
+
//
|
|
804
|
+
|
|
805
|
+
let transmissionNode = null;
|
|
806
|
+
let transmissionColorNode = null;
|
|
807
|
+
|
|
808
|
+
if ( inputs.transmission ) transmissionNode = inputs.transmission;
|
|
809
|
+
if ( inputs.transmission_color ) transmissionColorNode = inputs.transmission_color;
|
|
810
|
+
|
|
811
|
+
//
|
|
812
|
+
|
|
813
|
+
let thinFilmThicknessNode = null;
|
|
814
|
+
let thinFilmIorNode = null;
|
|
815
|
+
|
|
816
|
+
if ( inputs.thin_film_thickness ) thinFilmThicknessNode = inputs.thin_film_thickness;
|
|
817
|
+
|
|
818
|
+
if ( inputs.thin_film_ior ) {
|
|
819
|
+
|
|
820
|
+
// Clamp IOR to valid range for Three.js (1.0 to 2.333)
|
|
821
|
+
thinFilmIorNode = clamp( inputs.thin_film_ior, float( 1.0 ), float( 2.333 ) );
|
|
822
|
+
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
//
|
|
826
|
+
|
|
827
|
+
let sheenNode = null;
|
|
828
|
+
let sheenColorNode = null;
|
|
829
|
+
let sheenRoughnessNode = null;
|
|
830
|
+
|
|
831
|
+
if ( inputs.sheen ) sheenNode = inputs.sheen;
|
|
832
|
+
if ( inputs.sheen_color ) sheenColorNode = inputs.sheen_color;
|
|
833
|
+
if ( inputs.sheen_roughness ) sheenRoughnessNode = inputs.sheen_roughness;
|
|
834
|
+
|
|
835
|
+
//
|
|
836
|
+
|
|
688
837
|
let clearcoatNode = null;
|
|
689
838
|
let clearcoatRoughnessNode = null;
|
|
690
839
|
|
|
@@ -717,13 +866,46 @@ class MaterialXNode {
|
|
|
717
866
|
//
|
|
718
867
|
|
|
719
868
|
material.colorNode = colorNode || color( 0.8, 0.8, 0.8 );
|
|
869
|
+
material.opacityNode = opacityNode || float( 1.0 );
|
|
720
870
|
material.roughnessNode = roughnessNode || float( 0.2 );
|
|
721
871
|
material.metalnessNode = metalnessNode || float( 0 );
|
|
872
|
+
material.specularIntensityNode = specularIntensityNode || float( 0.5 );
|
|
873
|
+
material.specularColorNode = specularColorNode || color( 1.0, 1.0, 1.0 );
|
|
874
|
+
material.iorNode = iorNode || float( 1.5 );
|
|
875
|
+
material.anisotropyNode = anisotropyNode || float( 0 );
|
|
876
|
+
material.anisotropyRotationNode = anisotropyRotationNode || float( 0 );
|
|
877
|
+
material.transmissionNode = transmissionNode || float( 0 );
|
|
878
|
+
material.transmissionColorNode = transmissionColorNode || color( 1.0, 1.0, 1.0 );
|
|
879
|
+
material.thinFilmThicknessNode = thinFilmThicknessNode || float( 0 );
|
|
880
|
+
material.thinFilmIorNode = thinFilmIorNode || float( 1.5 );
|
|
881
|
+
material.sheenNode = sheenNode || float( 0 );
|
|
882
|
+
material.sheenColorNode = sheenColorNode || color( 1.0, 1.0, 1.0 );
|
|
883
|
+
material.sheenRoughnessNode = sheenRoughnessNode || float( 0.5 );
|
|
722
884
|
material.clearcoatNode = clearcoatNode || float( 0 );
|
|
723
885
|
material.clearcoatRoughnessNode = clearcoatRoughnessNode || float( 0 );
|
|
724
886
|
if ( normalNode ) material.normalNode = normalNode;
|
|
725
887
|
if ( emissiveNode ) material.emissiveNode = emissiveNode;
|
|
726
888
|
|
|
889
|
+
// Auto-enable iridescence when thin film parameters are present
|
|
890
|
+
if ( thinFilmThicknessNode && thinFilmThicknessNode.value !== undefined && thinFilmThicknessNode.value > 0 ) {
|
|
891
|
+
|
|
892
|
+
material.iridescence = 1.0;
|
|
893
|
+
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
if ( opacityNode !== null ) {
|
|
897
|
+
|
|
898
|
+
material.transparent = true;
|
|
899
|
+
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if ( transmissionNode !== null ) {
|
|
903
|
+
|
|
904
|
+
material.side = DoubleSide;
|
|
905
|
+
material.transparent = true;
|
|
906
|
+
|
|
907
|
+
}
|
|
908
|
+
|
|
727
909
|
}
|
|
728
910
|
|
|
729
911
|
/*setGltfPBR( material ) {
|
|
@@ -152,7 +152,19 @@ class TTFLoader extends Loader {
|
|
|
152
152
|
|
|
153
153
|
} );
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
if ( Array.isArray( glyph.unicodes ) && glyph.unicodes.length > 0 ) {
|
|
156
|
+
|
|
157
|
+
glyph.unicodes.forEach( function ( unicode ) {
|
|
158
|
+
|
|
159
|
+
glyphs[ String.fromCodePoint( unicode ) ] = token;
|
|
160
|
+
|
|
161
|
+
} );
|
|
162
|
+
|
|
163
|
+
} else {
|
|
164
|
+
|
|
165
|
+
glyphs[ String.fromCodePoint( glyph.unicode ) ] = token;
|
|
166
|
+
|
|
167
|
+
}
|
|
156
168
|
|
|
157
169
|
}
|
|
158
170
|
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FileLoader,
|
|
3
|
+
Loader
|
|
4
|
+
} from 'three';
|
|
5
|
+
|
|
6
|
+
import * as fflate from '../libs/fflate.module.js';
|
|
7
|
+
import { USDAParser } from './usd/USDAParser.js';
|
|
8
|
+
import { USDCParser } from './usd/USDCParser.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A loader for the USDZ format.
|
|
12
|
+
*
|
|
13
|
+
* USDZ files that use USDC internally are not yet supported, only USDA.
|
|
14
|
+
*
|
|
15
|
+
* ```js
|
|
16
|
+
* const loader = new USDZLoader();
|
|
17
|
+
* const model = await loader.loadAsync( 'saeukkang.usdz' );
|
|
18
|
+
* scene.add( model );
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @augments Loader
|
|
22
|
+
* @three_import import { USDLoader } from 'three/addons/loaders/USDLoader.js';
|
|
23
|
+
*/
|
|
24
|
+
class USDLoader extends Loader {
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Constructs a new USDZ loader.
|
|
28
|
+
*
|
|
29
|
+
* @param {LoadingManager} [manager] - The loading manager.
|
|
30
|
+
*/
|
|
31
|
+
constructor( manager ) {
|
|
32
|
+
|
|
33
|
+
super( manager );
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Starts loading from the given URL and passes the loaded USDZ asset
|
|
39
|
+
* to the `onLoad()` callback.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
|
|
42
|
+
* @param {function(Group)} onLoad - Executed when the loading process has been finished.
|
|
43
|
+
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
|
|
44
|
+
* @param {onErrorCallback} onError - Executed when errors occur.
|
|
45
|
+
*/
|
|
46
|
+
load( url, onLoad, onProgress, onError ) {
|
|
47
|
+
|
|
48
|
+
const scope = this;
|
|
49
|
+
|
|
50
|
+
const loader = new FileLoader( scope.manager );
|
|
51
|
+
loader.setPath( scope.path );
|
|
52
|
+
loader.setResponseType( 'arraybuffer' );
|
|
53
|
+
loader.setRequestHeader( scope.requestHeader );
|
|
54
|
+
loader.setWithCredentials( scope.withCredentials );
|
|
55
|
+
loader.load( url, function ( text ) {
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
|
|
59
|
+
onLoad( scope.parse( text ) );
|
|
60
|
+
|
|
61
|
+
} catch ( e ) {
|
|
62
|
+
|
|
63
|
+
if ( onError ) {
|
|
64
|
+
|
|
65
|
+
onError( e );
|
|
66
|
+
|
|
67
|
+
} else {
|
|
68
|
+
|
|
69
|
+
console.error( e );
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
scope.manager.itemError( url );
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
}, onProgress, onError );
|
|
78
|
+
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Parses the given USDZ data and returns the resulting group.
|
|
83
|
+
*
|
|
84
|
+
* @param {ArrayBuffer|string} buffer - The raw USDZ data as an array buffer.
|
|
85
|
+
* @return {Group} The parsed asset as a group.
|
|
86
|
+
*/
|
|
87
|
+
parse( buffer ) {
|
|
88
|
+
|
|
89
|
+
const usda = new USDAParser();
|
|
90
|
+
const usdc = new USDCParser();
|
|
91
|
+
|
|
92
|
+
function parseAssets( zip ) {
|
|
93
|
+
|
|
94
|
+
const data = {};
|
|
95
|
+
const loader = new FileLoader();
|
|
96
|
+
loader.setResponseType( 'arraybuffer' );
|
|
97
|
+
|
|
98
|
+
for ( const filename in zip ) {
|
|
99
|
+
|
|
100
|
+
if ( filename.endsWith( 'png' ) ) {
|
|
101
|
+
|
|
102
|
+
const blob = new Blob( [ zip[ filename ] ], { type: 'image/png' } );
|
|
103
|
+
data[ filename ] = URL.createObjectURL( blob );
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if ( filename.endsWith( 'usd' ) || filename.endsWith( 'usda' ) || filename.endsWith( 'usdc' ) ) {
|
|
108
|
+
|
|
109
|
+
if ( isCrateFile( zip[ filename ] ) ) {
|
|
110
|
+
|
|
111
|
+
data[ filename ] = usdc.parse( zip[ filename ].buffer, data );
|
|
112
|
+
|
|
113
|
+
} else {
|
|
114
|
+
|
|
115
|
+
const text = fflate.strFromU8( zip[ filename ] );
|
|
116
|
+
data[ filename ] = usda.parseText( text );
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return data;
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function isCrateFile( buffer ) {
|
|
129
|
+
|
|
130
|
+
const crateHeader = new Uint8Array( [ 0x50, 0x58, 0x52, 0x2D, 0x55, 0x53, 0x44, 0x43 ] ); // PXR-USDC
|
|
131
|
+
|
|
132
|
+
if ( buffer.byteLength < crateHeader.length ) return false;
|
|
133
|
+
|
|
134
|
+
const view = new Uint8Array( buffer, 0, crateHeader.length );
|
|
135
|
+
|
|
136
|
+
for ( let i = 0; i < crateHeader.length; i ++ ) {
|
|
137
|
+
|
|
138
|
+
if ( view[ i ] !== crateHeader[ i ] ) return false;
|
|
139
|
+
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return true;
|
|
143
|
+
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function findUSD( zip ) {
|
|
147
|
+
|
|
148
|
+
if ( zip.length < 1 ) return undefined;
|
|
149
|
+
|
|
150
|
+
const firstFileName = Object.keys( zip )[ 0 ];
|
|
151
|
+
let isCrate = false;
|
|
152
|
+
|
|
153
|
+
// As per the USD specification, the first entry in the zip archive is used as the main file ("UsdStage").
|
|
154
|
+
// ASCII files can end in either .usda or .usd.
|
|
155
|
+
// See https://openusd.org/release/spec_usdz.html#layout
|
|
156
|
+
if ( firstFileName.endsWith( 'usda' ) ) return zip[ firstFileName ];
|
|
157
|
+
|
|
158
|
+
if ( firstFileName.endsWith( 'usdc' ) ) {
|
|
159
|
+
|
|
160
|
+
isCrate = true;
|
|
161
|
+
|
|
162
|
+
} else if ( firstFileName.endsWith( 'usd' ) ) {
|
|
163
|
+
|
|
164
|
+
// If this is not a crate file, we assume it is a plain USDA file.
|
|
165
|
+
if ( ! isCrateFile( zip[ firstFileName ] ) ) {
|
|
166
|
+
|
|
167
|
+
return zip[ firstFileName ];
|
|
168
|
+
|
|
169
|
+
} else {
|
|
170
|
+
|
|
171
|
+
isCrate = true;
|
|
172
|
+
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if ( isCrate ) {
|
|
178
|
+
|
|
179
|
+
return zip[ firstFileName ];
|
|
180
|
+
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// USDA
|
|
186
|
+
|
|
187
|
+
if ( typeof buffer === 'string' ) {
|
|
188
|
+
|
|
189
|
+
return usda.parse( buffer, {} );
|
|
190
|
+
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// USDC
|
|
194
|
+
|
|
195
|
+
if ( isCrateFile( buffer ) ) {
|
|
196
|
+
|
|
197
|
+
return usdc.parse( buffer );
|
|
198
|
+
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// USDZ
|
|
202
|
+
|
|
203
|
+
const zip = fflate.unzipSync( new Uint8Array( buffer ) );
|
|
204
|
+
|
|
205
|
+
const assets = parseAssets( zip );
|
|
206
|
+
|
|
207
|
+
// console.log( assets );
|
|
208
|
+
|
|
209
|
+
const file = findUSD( zip );
|
|
210
|
+
|
|
211
|
+
const text = fflate.strFromU8( file );
|
|
212
|
+
|
|
213
|
+
return usda.parse( text, assets );
|
|
214
|
+
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export { USDLoader };
|