@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,904 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BufferAttribute,
|
|
3
|
-
BufferGeometry,
|
|
4
|
-
ClampToEdgeWrapping,
|
|
5
|
-
FileLoader,
|
|
6
|
-
Group,
|
|
7
|
-
NoColorSpace,
|
|
8
|
-
Loader,
|
|
9
|
-
Mesh,
|
|
10
|
-
MeshPhysicalMaterial,
|
|
11
|
-
MirroredRepeatWrapping,
|
|
12
|
-
RepeatWrapping,
|
|
13
|
-
SRGBColorSpace,
|
|
14
|
-
TextureLoader,
|
|
15
|
-
Object3D,
|
|
16
|
-
Vector2
|
|
17
|
-
} from 'three';
|
|
1
|
+
import { USDLoader } from './USDLoader.js';
|
|
18
2
|
|
|
19
|
-
|
|
3
|
+
// @deprecated, r179
|
|
20
4
|
|
|
21
|
-
class
|
|
5
|
+
class USDZLoader extends USDLoader {
|
|
22
6
|
|
|
23
|
-
parse( text ) {
|
|
24
|
-
|
|
25
|
-
const data = {};
|
|
26
|
-
|
|
27
|
-
const lines = text.split( '\n' );
|
|
28
|
-
|
|
29
|
-
let string = null;
|
|
30
|
-
let target = data;
|
|
31
|
-
|
|
32
|
-
const stack = [ data ];
|
|
33
|
-
|
|
34
|
-
// debugger;
|
|
35
|
-
|
|
36
|
-
for ( const line of lines ) {
|
|
37
|
-
|
|
38
|
-
// console.log( line );
|
|
39
|
-
|
|
40
|
-
if ( line.includes( '=' ) ) {
|
|
41
|
-
|
|
42
|
-
const assignment = line.split( '=' );
|
|
43
|
-
|
|
44
|
-
const lhs = assignment[ 0 ].trim();
|
|
45
|
-
const rhs = assignment[ 1 ].trim();
|
|
46
|
-
|
|
47
|
-
if ( rhs.endsWith( '{' ) ) {
|
|
48
|
-
|
|
49
|
-
const group = {};
|
|
50
|
-
stack.push( group );
|
|
51
|
-
|
|
52
|
-
target[ lhs ] = group;
|
|
53
|
-
target = group;
|
|
54
|
-
|
|
55
|
-
} else if ( rhs.endsWith( '(' ) ) {
|
|
56
|
-
|
|
57
|
-
// see #28631
|
|
58
|
-
|
|
59
|
-
const values = rhs.slice( 0, - 1 );
|
|
60
|
-
target[ lhs ] = values;
|
|
61
|
-
|
|
62
|
-
const meta = {};
|
|
63
|
-
stack.push( meta );
|
|
64
|
-
|
|
65
|
-
target = meta;
|
|
66
|
-
|
|
67
|
-
} else {
|
|
68
|
-
|
|
69
|
-
target[ lhs ] = rhs;
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
} else if ( line.endsWith( '{' ) ) {
|
|
74
|
-
|
|
75
|
-
const group = target[ string ] || {};
|
|
76
|
-
stack.push( group );
|
|
77
|
-
|
|
78
|
-
target[ string ] = group;
|
|
79
|
-
target = group;
|
|
80
|
-
|
|
81
|
-
} else if ( line.endsWith( '}' ) ) {
|
|
82
|
-
|
|
83
|
-
stack.pop();
|
|
84
|
-
|
|
85
|
-
if ( stack.length === 0 ) continue;
|
|
86
|
-
|
|
87
|
-
target = stack[ stack.length - 1 ];
|
|
88
|
-
|
|
89
|
-
} else if ( line.endsWith( '(' ) ) {
|
|
90
|
-
|
|
91
|
-
const meta = {};
|
|
92
|
-
stack.push( meta );
|
|
93
|
-
|
|
94
|
-
string = line.split( '(' )[ 0 ].trim() || string;
|
|
95
|
-
|
|
96
|
-
target[ string ] = meta;
|
|
97
|
-
target = meta;
|
|
98
|
-
|
|
99
|
-
} else if ( line.endsWith( ')' ) ) {
|
|
100
|
-
|
|
101
|
-
stack.pop();
|
|
102
|
-
|
|
103
|
-
target = stack[ stack.length - 1 ];
|
|
104
|
-
|
|
105
|
-
} else {
|
|
106
|
-
|
|
107
|
-
string = line.trim();
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return data;
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* A loader for the USDZ format.
|
|
121
|
-
*
|
|
122
|
-
* USDZ files that use USDC internally are not yet supported, only USDA.
|
|
123
|
-
*
|
|
124
|
-
* ```js
|
|
125
|
-
* const loader = new USDZLoader();
|
|
126
|
-
* const model = await loader.loadAsync( 'saeukkang.usdz' );
|
|
127
|
-
* scene.add( model );
|
|
128
|
-
* ```
|
|
129
|
-
*
|
|
130
|
-
* @augments Loader
|
|
131
|
-
* @three_import import { USDZLoader } from 'three/addons/loaders/USDZLoader.js';
|
|
132
|
-
*/
|
|
133
|
-
class USDZLoader extends Loader {
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Constructs a new USDZ loader.
|
|
137
|
-
*
|
|
138
|
-
* @param {LoadingManager} [manager] - The loading manager.
|
|
139
|
-
*/
|
|
140
7
|
constructor( manager ) {
|
|
141
8
|
|
|
9
|
+
console.warn( 'USDZLoader has been deprecated. Please use USDLoader instead.' );
|
|
142
10
|
super( manager );
|
|
143
11
|
|
|
144
12
|
}
|
|
145
13
|
|
|
146
|
-
/**
|
|
147
|
-
* Starts loading from the given URL and passes the loaded USDZ asset
|
|
148
|
-
* to the `onLoad()` callback.
|
|
149
|
-
*
|
|
150
|
-
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
|
|
151
|
-
* @param {function(Group)} onLoad - Executed when the loading process has been finished.
|
|
152
|
-
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
|
|
153
|
-
* @param {onErrorCallback} onError - Executed when errors occur.
|
|
154
|
-
*/
|
|
155
|
-
load( url, onLoad, onProgress, onError ) {
|
|
156
|
-
|
|
157
|
-
const scope = this;
|
|
158
|
-
|
|
159
|
-
const loader = new FileLoader( scope.manager );
|
|
160
|
-
loader.setPath( scope.path );
|
|
161
|
-
loader.setResponseType( 'arraybuffer' );
|
|
162
|
-
loader.setRequestHeader( scope.requestHeader );
|
|
163
|
-
loader.setWithCredentials( scope.withCredentials );
|
|
164
|
-
loader.load( url, function ( text ) {
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
|
|
168
|
-
onLoad( scope.parse( text ) );
|
|
169
|
-
|
|
170
|
-
} catch ( e ) {
|
|
171
|
-
|
|
172
|
-
if ( onError ) {
|
|
173
|
-
|
|
174
|
-
onError( e );
|
|
175
|
-
|
|
176
|
-
} else {
|
|
177
|
-
|
|
178
|
-
console.error( e );
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
scope.manager.itemError( url );
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
}, onProgress, onError );
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Parses the given USDZ data and returns the resulting group.
|
|
192
|
-
*
|
|
193
|
-
* @param {ArrayBuffer} buffer - The raw USDZ data as an array buffer.
|
|
194
|
-
* @return {Group} The parsed asset as a group.
|
|
195
|
-
*/
|
|
196
|
-
parse( buffer ) {
|
|
197
|
-
|
|
198
|
-
const parser = new USDAParser();
|
|
199
|
-
|
|
200
|
-
function parseAssets( zip ) {
|
|
201
|
-
|
|
202
|
-
const data = {};
|
|
203
|
-
const loader = new FileLoader();
|
|
204
|
-
loader.setResponseType( 'arraybuffer' );
|
|
205
|
-
|
|
206
|
-
for ( const filename in zip ) {
|
|
207
|
-
|
|
208
|
-
if ( filename.endsWith( 'png' ) ) {
|
|
209
|
-
|
|
210
|
-
const blob = new Blob( [ zip[ filename ] ], { type: 'image/png' } );
|
|
211
|
-
data[ filename ] = URL.createObjectURL( blob );
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if ( filename.endsWith( 'usd' ) || filename.endsWith( 'usda' ) ) {
|
|
216
|
-
|
|
217
|
-
if ( isCrateFile( zip[ filename ] ) ) {
|
|
218
|
-
|
|
219
|
-
throw Error( 'THREE.USDZLoader: Crate files (.usdc or binary .usd) are not supported.' );
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const text = fflate.strFromU8( zip[ filename ] );
|
|
224
|
-
data[ filename ] = parser.parse( text );
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return data;
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function isCrateFile( buffer ) {
|
|
235
|
-
|
|
236
|
-
// Check if this a crate file. First 7 bytes of a crate file are "PXR-USDC".
|
|
237
|
-
const fileHeader = buffer.slice( 0, 7 );
|
|
238
|
-
const crateHeader = new Uint8Array( [ 0x50, 0x58, 0x52, 0x2D, 0x55, 0x53, 0x44, 0x43 ] );
|
|
239
|
-
|
|
240
|
-
// If this is not a crate file, we assume it is a plain USDA file.
|
|
241
|
-
return fileHeader.every( ( value, index ) => value === crateHeader[ index ] );
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function findUSD( zip ) {
|
|
246
|
-
|
|
247
|
-
if ( zip.length < 1 ) return undefined;
|
|
248
|
-
|
|
249
|
-
const firstFileName = Object.keys( zip )[ 0 ];
|
|
250
|
-
let isCrate = false;
|
|
251
|
-
|
|
252
|
-
// As per the USD specification, the first entry in the zip archive is used as the main file ("UsdStage").
|
|
253
|
-
// ASCII files can end in either .usda or .usd.
|
|
254
|
-
// See https://openusd.org/release/spec_usdz.html#layout
|
|
255
|
-
if ( firstFileName.endsWith( 'usda' ) ) return zip[ firstFileName ];
|
|
256
|
-
|
|
257
|
-
if ( firstFileName.endsWith( 'usdc' ) ) {
|
|
258
|
-
|
|
259
|
-
isCrate = true;
|
|
260
|
-
|
|
261
|
-
} else if ( firstFileName.endsWith( 'usd' ) ) {
|
|
262
|
-
|
|
263
|
-
// If this is not a crate file, we assume it is a plain USDA file.
|
|
264
|
-
if ( ! isCrateFile( zip[ firstFileName ] ) ) {
|
|
265
|
-
|
|
266
|
-
return zip[ firstFileName ];
|
|
267
|
-
|
|
268
|
-
} else {
|
|
269
|
-
|
|
270
|
-
isCrate = true;
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if ( isCrate ) {
|
|
277
|
-
|
|
278
|
-
throw Error( 'THREE.USDZLoader: Crate files (.usdc or binary .usd) are not supported.' );
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
const zip = fflate.unzipSync( new Uint8Array( buffer ) );
|
|
285
|
-
|
|
286
|
-
// console.log( zip );
|
|
287
|
-
|
|
288
|
-
const assets = parseAssets( zip );
|
|
289
|
-
|
|
290
|
-
// console.log( assets )
|
|
291
|
-
|
|
292
|
-
const file = findUSD( zip );
|
|
293
|
-
|
|
294
|
-
// Parse file
|
|
295
|
-
|
|
296
|
-
const text = fflate.strFromU8( file );
|
|
297
|
-
const root = parser.parse( text );
|
|
298
|
-
|
|
299
|
-
// Build scene
|
|
300
|
-
|
|
301
|
-
function findMeshGeometry( data ) {
|
|
302
|
-
|
|
303
|
-
if ( ! data ) return undefined;
|
|
304
|
-
|
|
305
|
-
if ( 'prepend references' in data ) {
|
|
306
|
-
|
|
307
|
-
const reference = data[ 'prepend references' ];
|
|
308
|
-
const parts = reference.split( '@' );
|
|
309
|
-
const path = parts[ 1 ].replace( /^.\//, '' );
|
|
310
|
-
const id = parts[ 2 ].replace( /^<\//, '' ).replace( />$/, '' );
|
|
311
|
-
|
|
312
|
-
return findGeometry( assets[ path ], id );
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return findGeometry( data );
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
function findGeometry( data, id ) {
|
|
321
|
-
|
|
322
|
-
if ( ! data ) return undefined;
|
|
323
|
-
|
|
324
|
-
if ( id !== undefined ) {
|
|
325
|
-
|
|
326
|
-
const def = `def Mesh "${id}"`;
|
|
327
|
-
|
|
328
|
-
if ( def in data ) {
|
|
329
|
-
|
|
330
|
-
return data[ def ];
|
|
331
|
-
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
for ( const name in data ) {
|
|
337
|
-
|
|
338
|
-
const object = data[ name ];
|
|
339
|
-
|
|
340
|
-
if ( name.startsWith( 'def Mesh' ) ) {
|
|
341
|
-
|
|
342
|
-
return object;
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if ( typeof object === 'object' ) {
|
|
348
|
-
|
|
349
|
-
const geometry = findGeometry( object );
|
|
350
|
-
|
|
351
|
-
if ( geometry ) return geometry;
|
|
352
|
-
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
function buildGeometry( data ) {
|
|
360
|
-
|
|
361
|
-
if ( ! data ) return undefined;
|
|
362
|
-
|
|
363
|
-
const geometry = new BufferGeometry();
|
|
364
|
-
let indices = null;
|
|
365
|
-
let counts = null;
|
|
366
|
-
let uvs = null;
|
|
367
|
-
|
|
368
|
-
let positionsLength = - 1;
|
|
369
|
-
|
|
370
|
-
// index
|
|
371
|
-
|
|
372
|
-
if ( 'int[] faceVertexIndices' in data ) {
|
|
373
|
-
|
|
374
|
-
indices = JSON.parse( data[ 'int[] faceVertexIndices' ] );
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// face count
|
|
379
|
-
|
|
380
|
-
if ( 'int[] faceVertexCounts' in data ) {
|
|
381
|
-
|
|
382
|
-
counts = JSON.parse( data[ 'int[] faceVertexCounts' ] );
|
|
383
|
-
indices = toTriangleIndices( indices, counts );
|
|
384
|
-
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// position
|
|
388
|
-
|
|
389
|
-
if ( 'point3f[] points' in data ) {
|
|
390
|
-
|
|
391
|
-
const positions = JSON.parse( data[ 'point3f[] points' ].replace( /[()]*/g, '' ) );
|
|
392
|
-
positionsLength = positions.length;
|
|
393
|
-
let attribute = new BufferAttribute( new Float32Array( positions ), 3 );
|
|
394
|
-
|
|
395
|
-
if ( indices !== null ) attribute = toFlatBufferAttribute( attribute, indices );
|
|
396
|
-
|
|
397
|
-
geometry.setAttribute( 'position', attribute );
|
|
398
|
-
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// uv
|
|
402
|
-
|
|
403
|
-
if ( 'float2[] primvars:st' in data ) {
|
|
404
|
-
|
|
405
|
-
data[ 'texCoord2f[] primvars:st' ] = data[ 'float2[] primvars:st' ];
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
if ( 'texCoord2f[] primvars:st' in data ) {
|
|
410
|
-
|
|
411
|
-
uvs = JSON.parse( data[ 'texCoord2f[] primvars:st' ].replace( /[()]*/g, '' ) );
|
|
412
|
-
let attribute = new BufferAttribute( new Float32Array( uvs ), 2 );
|
|
413
|
-
|
|
414
|
-
if ( indices !== null ) attribute = toFlatBufferAttribute( attribute, indices );
|
|
415
|
-
|
|
416
|
-
geometry.setAttribute( 'uv', attribute );
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
if ( 'int[] primvars:st:indices' in data && uvs !== null ) {
|
|
421
|
-
|
|
422
|
-
// custom uv index, overwrite uvs with new data
|
|
423
|
-
|
|
424
|
-
const attribute = new BufferAttribute( new Float32Array( uvs ), 2 );
|
|
425
|
-
let indices = JSON.parse( data[ 'int[] primvars:st:indices' ] );
|
|
426
|
-
indices = toTriangleIndices( indices, counts );
|
|
427
|
-
geometry.setAttribute( 'uv', toFlatBufferAttribute( attribute, indices ) );
|
|
428
|
-
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// normal
|
|
432
|
-
|
|
433
|
-
if ( 'normal3f[] normals' in data ) {
|
|
434
|
-
|
|
435
|
-
const normals = JSON.parse( data[ 'normal3f[] normals' ].replace( /[()]*/g, '' ) );
|
|
436
|
-
let attribute = new BufferAttribute( new Float32Array( normals ), 3 );
|
|
437
|
-
|
|
438
|
-
// normals require a special treatment in USD
|
|
439
|
-
|
|
440
|
-
if ( normals.length === positionsLength ) {
|
|
441
|
-
|
|
442
|
-
// raw normal and position data have equal length (like produced by USDZExporter)
|
|
443
|
-
|
|
444
|
-
if ( indices !== null ) attribute = toFlatBufferAttribute( attribute, indices );
|
|
445
|
-
|
|
446
|
-
} else {
|
|
447
|
-
|
|
448
|
-
// unequal length, normals are independent of faceVertexIndices
|
|
449
|
-
|
|
450
|
-
let indices = Array.from( Array( normals.length / 3 ).keys() ); // [ 0, 1, 2, 3 ... ]
|
|
451
|
-
indices = toTriangleIndices( indices, counts );
|
|
452
|
-
attribute = toFlatBufferAttribute( attribute, indices );
|
|
453
|
-
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
geometry.setAttribute( 'normal', attribute );
|
|
457
|
-
|
|
458
|
-
} else {
|
|
459
|
-
|
|
460
|
-
// compute flat vertex normals
|
|
461
|
-
|
|
462
|
-
geometry.computeVertexNormals();
|
|
463
|
-
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
return geometry;
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
function toTriangleIndices( rawIndices, counts ) {
|
|
471
|
-
|
|
472
|
-
const indices = [];
|
|
473
|
-
|
|
474
|
-
for ( let i = 0; i < counts.length; i ++ ) {
|
|
475
|
-
|
|
476
|
-
const count = counts[ i ];
|
|
477
|
-
|
|
478
|
-
const stride = i * count;
|
|
479
|
-
|
|
480
|
-
if ( count === 3 ) {
|
|
481
|
-
|
|
482
|
-
const a = rawIndices[ stride + 0 ];
|
|
483
|
-
const b = rawIndices[ stride + 1 ];
|
|
484
|
-
const c = rawIndices[ stride + 2 ];
|
|
485
|
-
|
|
486
|
-
indices.push( a, b, c );
|
|
487
|
-
|
|
488
|
-
} else if ( count === 4 ) {
|
|
489
|
-
|
|
490
|
-
const a = rawIndices[ stride + 0 ];
|
|
491
|
-
const b = rawIndices[ stride + 1 ];
|
|
492
|
-
const c = rawIndices[ stride + 2 ];
|
|
493
|
-
const d = rawIndices[ stride + 3 ];
|
|
494
|
-
|
|
495
|
-
indices.push( a, b, c );
|
|
496
|
-
indices.push( a, c, d );
|
|
497
|
-
|
|
498
|
-
} else {
|
|
499
|
-
|
|
500
|
-
console.warn( 'THREE.USDZLoader: Face vertex count of %s unsupported.', count );
|
|
501
|
-
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
return indices;
|
|
507
|
-
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
function toFlatBufferAttribute( attribute, indices ) {
|
|
511
|
-
|
|
512
|
-
const array = attribute.array;
|
|
513
|
-
const itemSize = attribute.itemSize;
|
|
514
|
-
|
|
515
|
-
const array2 = new array.constructor( indices.length * itemSize );
|
|
516
|
-
|
|
517
|
-
let index = 0, index2 = 0;
|
|
518
|
-
|
|
519
|
-
for ( let i = 0, l = indices.length; i < l; i ++ ) {
|
|
520
|
-
|
|
521
|
-
index = indices[ i ] * itemSize;
|
|
522
|
-
|
|
523
|
-
for ( let j = 0; j < itemSize; j ++ ) {
|
|
524
|
-
|
|
525
|
-
array2[ index2 ++ ] = array[ index ++ ];
|
|
526
|
-
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
return new BufferAttribute( array2, itemSize );
|
|
532
|
-
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
function findMeshMaterial( data ) {
|
|
536
|
-
|
|
537
|
-
if ( ! data ) return undefined;
|
|
538
|
-
|
|
539
|
-
if ( 'rel material:binding' in data ) {
|
|
540
|
-
|
|
541
|
-
const reference = data[ 'rel material:binding' ];
|
|
542
|
-
const id = reference.replace( /^<\//, '' ).replace( />$/, '' );
|
|
543
|
-
const parts = id.split( '/' );
|
|
544
|
-
|
|
545
|
-
return findMaterial( root, ` "${ parts[ 1 ] }"` );
|
|
546
|
-
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
return findMaterial( data );
|
|
550
|
-
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
function findMaterial( data, id = '' ) {
|
|
554
|
-
|
|
555
|
-
for ( const name in data ) {
|
|
556
|
-
|
|
557
|
-
const object = data[ name ];
|
|
558
|
-
|
|
559
|
-
if ( name.startsWith( 'def Material' + id ) ) {
|
|
560
|
-
|
|
561
|
-
return object;
|
|
562
|
-
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
if ( typeof object === 'object' ) {
|
|
566
|
-
|
|
567
|
-
const material = findMaterial( object, id );
|
|
568
|
-
|
|
569
|
-
if ( material ) return material;
|
|
570
|
-
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
function setTextureParams( map, data_value ) {
|
|
578
|
-
|
|
579
|
-
// rotation, scale and translation
|
|
580
|
-
|
|
581
|
-
if ( data_value[ 'float inputs:rotation' ] ) {
|
|
582
|
-
|
|
583
|
-
map.rotation = parseFloat( data_value[ 'float inputs:rotation' ] );
|
|
584
|
-
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
if ( data_value[ 'float2 inputs:scale' ] ) {
|
|
588
|
-
|
|
589
|
-
map.repeat = new Vector2().fromArray( JSON.parse( '[' + data_value[ 'float2 inputs:scale' ].replace( /[()]*/g, '' ) + ']' ) );
|
|
590
|
-
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
if ( data_value[ 'float2 inputs:translation' ] ) {
|
|
594
|
-
|
|
595
|
-
map.offset = new Vector2().fromArray( JSON.parse( '[' + data_value[ 'float2 inputs:translation' ].replace( /[()]*/g, '' ) + ']' ) );
|
|
596
|
-
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
function buildMaterial( data ) {
|
|
602
|
-
|
|
603
|
-
const material = new MeshPhysicalMaterial();
|
|
604
|
-
|
|
605
|
-
if ( data !== undefined ) {
|
|
606
|
-
|
|
607
|
-
const surfaceConnection = data[ 'token outputs:surface.connect' ];
|
|
608
|
-
const surfaceName = /(\w+).output/.exec( surfaceConnection )[ 1 ];
|
|
609
|
-
const surface = data[ `def Shader "${surfaceName}"` ];
|
|
610
|
-
|
|
611
|
-
if ( surface !== undefined ) {
|
|
612
|
-
|
|
613
|
-
if ( 'color3f inputs:diffuseColor.connect' in surface ) {
|
|
614
|
-
|
|
615
|
-
const path = surface[ 'color3f inputs:diffuseColor.connect' ];
|
|
616
|
-
const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
|
|
617
|
-
|
|
618
|
-
material.map = buildTexture( sampler );
|
|
619
|
-
material.map.colorSpace = SRGBColorSpace;
|
|
620
|
-
|
|
621
|
-
if ( 'def Shader "Transform2d_diffuse"' in data ) {
|
|
622
|
-
|
|
623
|
-
setTextureParams( material.map, data[ 'def Shader "Transform2d_diffuse"' ] );
|
|
624
|
-
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
} else if ( 'color3f inputs:diffuseColor' in surface ) {
|
|
628
|
-
|
|
629
|
-
const color = surface[ 'color3f inputs:diffuseColor' ].replace( /[()]*/g, '' );
|
|
630
|
-
material.color.fromArray( JSON.parse( '[' + color + ']' ) );
|
|
631
|
-
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
if ( 'color3f inputs:emissiveColor.connect' in surface ) {
|
|
635
|
-
|
|
636
|
-
const path = surface[ 'color3f inputs:emissiveColor.connect' ];
|
|
637
|
-
const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
|
|
638
|
-
|
|
639
|
-
material.emissiveMap = buildTexture( sampler );
|
|
640
|
-
material.emissiveMap.colorSpace = SRGBColorSpace;
|
|
641
|
-
material.emissive.set( 0xffffff );
|
|
642
|
-
|
|
643
|
-
if ( 'def Shader "Transform2d_emissive"' in data ) {
|
|
644
|
-
|
|
645
|
-
setTextureParams( material.emissiveMap, data[ 'def Shader "Transform2d_emissive"' ] );
|
|
646
|
-
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
} else if ( 'color3f inputs:emissiveColor' in surface ) {
|
|
650
|
-
|
|
651
|
-
const color = surface[ 'color3f inputs:emissiveColor' ].replace( /[()]*/g, '' );
|
|
652
|
-
material.emissive.fromArray( JSON.parse( '[' + color + ']' ) );
|
|
653
|
-
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
if ( 'normal3f inputs:normal.connect' in surface ) {
|
|
657
|
-
|
|
658
|
-
const path = surface[ 'normal3f inputs:normal.connect' ];
|
|
659
|
-
const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
|
|
660
|
-
|
|
661
|
-
material.normalMap = buildTexture( sampler );
|
|
662
|
-
material.normalMap.colorSpace = NoColorSpace;
|
|
663
|
-
|
|
664
|
-
if ( 'def Shader "Transform2d_normal"' in data ) {
|
|
665
|
-
|
|
666
|
-
setTextureParams( material.normalMap, data[ 'def Shader "Transform2d_normal"' ] );
|
|
667
|
-
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
if ( 'float inputs:roughness.connect' in surface ) {
|
|
673
|
-
|
|
674
|
-
const path = surface[ 'float inputs:roughness.connect' ];
|
|
675
|
-
const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
|
|
676
|
-
|
|
677
|
-
material.roughness = 1.0;
|
|
678
|
-
material.roughnessMap = buildTexture( sampler );
|
|
679
|
-
material.roughnessMap.colorSpace = NoColorSpace;
|
|
680
|
-
|
|
681
|
-
if ( 'def Shader "Transform2d_roughness"' in data ) {
|
|
682
|
-
|
|
683
|
-
setTextureParams( material.roughnessMap, data[ 'def Shader "Transform2d_roughness"' ] );
|
|
684
|
-
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
} else if ( 'float inputs:roughness' in surface ) {
|
|
688
|
-
|
|
689
|
-
material.roughness = parseFloat( surface[ 'float inputs:roughness' ] );
|
|
690
|
-
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
if ( 'float inputs:metallic.connect' in surface ) {
|
|
694
|
-
|
|
695
|
-
const path = surface[ 'float inputs:metallic.connect' ];
|
|
696
|
-
const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
|
|
697
|
-
|
|
698
|
-
material.metalness = 1.0;
|
|
699
|
-
material.metalnessMap = buildTexture( sampler );
|
|
700
|
-
material.metalnessMap.colorSpace = NoColorSpace;
|
|
701
|
-
|
|
702
|
-
if ( 'def Shader "Transform2d_metallic"' in data ) {
|
|
703
|
-
|
|
704
|
-
setTextureParams( material.metalnessMap, data[ 'def Shader "Transform2d_metallic"' ] );
|
|
705
|
-
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
} else if ( 'float inputs:metallic' in surface ) {
|
|
709
|
-
|
|
710
|
-
material.metalness = parseFloat( surface[ 'float inputs:metallic' ] );
|
|
711
|
-
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
if ( 'float inputs:clearcoat.connect' in surface ) {
|
|
715
|
-
|
|
716
|
-
const path = surface[ 'float inputs:clearcoat.connect' ];
|
|
717
|
-
const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
|
|
718
|
-
|
|
719
|
-
material.clearcoat = 1.0;
|
|
720
|
-
material.clearcoatMap = buildTexture( sampler );
|
|
721
|
-
material.clearcoatMap.colorSpace = NoColorSpace;
|
|
722
|
-
|
|
723
|
-
if ( 'def Shader "Transform2d_clearcoat"' in data ) {
|
|
724
|
-
|
|
725
|
-
setTextureParams( material.clearcoatMap, data[ 'def Shader "Transform2d_clearcoat"' ] );
|
|
726
|
-
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
} else if ( 'float inputs:clearcoat' in surface ) {
|
|
730
|
-
|
|
731
|
-
material.clearcoat = parseFloat( surface[ 'float inputs:clearcoat' ] );
|
|
732
|
-
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
if ( 'float inputs:clearcoatRoughness.connect' in surface ) {
|
|
736
|
-
|
|
737
|
-
const path = surface[ 'float inputs:clearcoatRoughness.connect' ];
|
|
738
|
-
const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
|
|
739
|
-
|
|
740
|
-
material.clearcoatRoughness = 1.0;
|
|
741
|
-
material.clearcoatRoughnessMap = buildTexture( sampler );
|
|
742
|
-
material.clearcoatRoughnessMap.colorSpace = NoColorSpace;
|
|
743
|
-
|
|
744
|
-
if ( 'def Shader "Transform2d_clearcoatRoughness"' in data ) {
|
|
745
|
-
|
|
746
|
-
setTextureParams( material.clearcoatRoughnessMap, data[ 'def Shader "Transform2d_clearcoatRoughness"' ] );
|
|
747
|
-
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
} else if ( 'float inputs:clearcoatRoughness' in surface ) {
|
|
751
|
-
|
|
752
|
-
material.clearcoatRoughness = parseFloat( surface[ 'float inputs:clearcoatRoughness' ] );
|
|
753
|
-
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
if ( 'float inputs:ior' in surface ) {
|
|
757
|
-
|
|
758
|
-
material.ior = parseFloat( surface[ 'float inputs:ior' ] );
|
|
759
|
-
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
if ( 'float inputs:occlusion.connect' in surface ) {
|
|
763
|
-
|
|
764
|
-
const path = surface[ 'float inputs:occlusion.connect' ];
|
|
765
|
-
const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
|
|
766
|
-
|
|
767
|
-
material.aoMap = buildTexture( sampler );
|
|
768
|
-
material.aoMap.colorSpace = NoColorSpace;
|
|
769
|
-
|
|
770
|
-
if ( 'def Shader "Transform2d_occlusion"' in data ) {
|
|
771
|
-
|
|
772
|
-
setTextureParams( material.aoMap, data[ 'def Shader "Transform2d_occlusion"' ] );
|
|
773
|
-
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
return material;
|
|
783
|
-
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
function findTexture( data, id ) {
|
|
787
|
-
|
|
788
|
-
for ( const name in data ) {
|
|
789
|
-
|
|
790
|
-
const object = data[ name ];
|
|
791
|
-
|
|
792
|
-
if ( name.startsWith( `def Shader "${ id }"` ) ) {
|
|
793
|
-
|
|
794
|
-
return object;
|
|
795
|
-
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
if ( typeof object === 'object' ) {
|
|
799
|
-
|
|
800
|
-
const texture = findTexture( object, id );
|
|
801
|
-
|
|
802
|
-
if ( texture ) return texture;
|
|
803
|
-
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
function buildTexture( data ) {
|
|
811
|
-
|
|
812
|
-
if ( 'asset inputs:file' in data ) {
|
|
813
|
-
|
|
814
|
-
const path = data[ 'asset inputs:file' ].replace( /@*/g, '' ).trim();
|
|
815
|
-
|
|
816
|
-
const loader = new TextureLoader();
|
|
817
|
-
|
|
818
|
-
const texture = loader.load( assets[ path ] );
|
|
819
|
-
|
|
820
|
-
const map = {
|
|
821
|
-
'"clamp"': ClampToEdgeWrapping,
|
|
822
|
-
'"mirror"': MirroredRepeatWrapping,
|
|
823
|
-
'"repeat"': RepeatWrapping
|
|
824
|
-
};
|
|
825
|
-
|
|
826
|
-
if ( 'token inputs:wrapS' in data ) {
|
|
827
|
-
|
|
828
|
-
texture.wrapS = map[ data[ 'token inputs:wrapS' ] ];
|
|
829
|
-
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
if ( 'token inputs:wrapT' in data ) {
|
|
833
|
-
|
|
834
|
-
texture.wrapT = map[ data[ 'token inputs:wrapT' ] ];
|
|
835
|
-
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
return texture;
|
|
839
|
-
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
return null;
|
|
843
|
-
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
function buildObject( data ) {
|
|
847
|
-
|
|
848
|
-
const geometry = buildGeometry( findMeshGeometry( data ) );
|
|
849
|
-
const material = buildMaterial( findMeshMaterial( data ) );
|
|
850
|
-
|
|
851
|
-
const mesh = geometry ? new Mesh( geometry, material ) : new Object3D();
|
|
852
|
-
|
|
853
|
-
if ( 'matrix4d xformOp:transform' in data ) {
|
|
854
|
-
|
|
855
|
-
const array = JSON.parse( '[' + data[ 'matrix4d xformOp:transform' ].replace( /[()]*/g, '' ) + ']' );
|
|
856
|
-
|
|
857
|
-
mesh.matrix.fromArray( array );
|
|
858
|
-
mesh.matrix.decompose( mesh.position, mesh.quaternion, mesh.scale );
|
|
859
|
-
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
return mesh;
|
|
863
|
-
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
function buildHierarchy( data, group ) {
|
|
867
|
-
|
|
868
|
-
for ( const name in data ) {
|
|
869
|
-
|
|
870
|
-
if ( name.startsWith( 'def Scope' ) ) {
|
|
871
|
-
|
|
872
|
-
buildHierarchy( data[ name ], group );
|
|
873
|
-
|
|
874
|
-
} else if ( name.startsWith( 'def Xform' ) ) {
|
|
875
|
-
|
|
876
|
-
const mesh = buildObject( data[ name ] );
|
|
877
|
-
|
|
878
|
-
if ( /def Xform "(\w+)"/.test( name ) ) {
|
|
879
|
-
|
|
880
|
-
mesh.name = /def Xform "(\w+)"/.exec( name )[ 1 ];
|
|
881
|
-
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
group.add( mesh );
|
|
885
|
-
|
|
886
|
-
buildHierarchy( data[ name ], mesh );
|
|
887
|
-
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
const group = new Group();
|
|
895
|
-
|
|
896
|
-
buildHierarchy( root, group );
|
|
897
|
-
|
|
898
|
-
return group;
|
|
899
|
-
|
|
900
|
-
}
|
|
901
|
-
|
|
902
14
|
}
|
|
903
15
|
|
|
904
16
|
export { USDZLoader };
|