super-three 0.181.0 → 0.184.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.
Files changed (539) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +3 -4
  3. package/build/three.cjs +13152 -11354
  4. package/build/three.core.js +12319 -11539
  5. package/build/three.core.min.js +2 -2
  6. package/build/three.module.js +1808 -781
  7. package/build/three.module.min.js +2 -2
  8. package/build/three.tsl.js +27 -13
  9. package/build/three.tsl.min.js +2 -2
  10. package/build/three.webgpu.js +10523 -6263
  11. package/build/three.webgpu.min.js +2 -2
  12. package/build/three.webgpu.nodes.js +10484 -6262
  13. package/build/three.webgpu.nodes.min.js +2 -2
  14. package/examples/jsm/Addons.js +11 -3
  15. package/examples/jsm/animation/CCDIKSolver.js +7 -3
  16. package/examples/jsm/controls/ArcballControls.js +7 -4
  17. package/examples/jsm/controls/DragControls.js +2 -2
  18. package/examples/jsm/controls/FirstPersonControls.js +58 -54
  19. package/examples/jsm/controls/FlyControls.js +4 -0
  20. package/examples/jsm/controls/MapControls.js +55 -1
  21. package/examples/jsm/controls/OrbitControls.js +111 -8
  22. package/examples/jsm/controls/TrackballControls.js +8 -8
  23. package/examples/jsm/controls/TransformControls.js +34 -2
  24. package/examples/jsm/csm/CSM.js +2 -1
  25. package/examples/jsm/csm/CSMShadowNode.js +6 -2
  26. package/examples/jsm/effects/AnaglyphEffect.js +102 -7
  27. package/examples/jsm/environments/ColorEnvironment.js +59 -0
  28. package/examples/jsm/environments/RoomEnvironment.js +3 -0
  29. package/examples/jsm/exporters/EXRExporter.js +1 -1
  30. package/examples/jsm/exporters/GLTFExporter.js +152 -9
  31. package/examples/jsm/exporters/USDZExporter.js +22 -3
  32. package/examples/jsm/geometries/DecalGeometry.js +1 -1
  33. package/examples/jsm/geometries/TextGeometry.js +18 -0
  34. package/examples/jsm/helpers/AnimationPathHelper.js +302 -0
  35. package/examples/jsm/helpers/LightProbeGridHelper.js +221 -0
  36. package/examples/jsm/helpers/LightProbeHelperGPU.js +1 -1
  37. package/examples/jsm/helpers/TextureHelperGPU.js +1 -1
  38. package/examples/jsm/helpers/ViewHelper.js +67 -8
  39. package/examples/jsm/inspector/Extension.js +13 -0
  40. package/examples/jsm/inspector/Inspector.js +203 -88
  41. package/examples/jsm/inspector/RendererInspector.js +14 -4
  42. package/examples/jsm/inspector/extensions/extensions.json +6 -0
  43. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +916 -0
  44. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +281 -0
  45. package/examples/jsm/inspector/tabs/Console.js +41 -7
  46. package/examples/jsm/inspector/tabs/Memory.js +128 -0
  47. package/examples/jsm/inspector/tabs/Parameters.js +51 -3
  48. package/examples/jsm/inspector/tabs/Performance.js +4 -4
  49. package/examples/jsm/inspector/tabs/Settings.js +264 -0
  50. package/examples/jsm/inspector/tabs/Timeline.js +1611 -0
  51. package/examples/jsm/inspector/tabs/Viewer.js +107 -5
  52. package/examples/jsm/inspector/ui/Graph.js +2 -2
  53. package/examples/jsm/inspector/ui/List.js +1 -1
  54. package/examples/jsm/inspector/ui/Profiler.js +1936 -34
  55. package/examples/jsm/inspector/ui/Style.js +1044 -31
  56. package/examples/jsm/inspector/ui/Tab.js +222 -3
  57. package/examples/jsm/inspector/ui/Values.js +55 -2
  58. package/examples/jsm/inspector/ui/utils.js +13 -0
  59. package/examples/jsm/interaction/InteractionManager.js +226 -0
  60. package/examples/jsm/libs/meshopt_decoder.module.js +9 -8
  61. package/examples/jsm/lighting/DynamicLighting.js +82 -0
  62. package/examples/jsm/lighting/LightProbeGrid.js +651 -0
  63. package/examples/jsm/lines/LineMaterial.js +7 -1
  64. package/examples/jsm/loaders/3DMLoader.js +5 -4
  65. package/examples/jsm/loaders/3MFLoader.js +2 -2
  66. package/examples/jsm/loaders/AMFLoader.js +2 -2
  67. package/examples/jsm/loaders/ColladaLoader.js +24 -4026
  68. package/examples/jsm/loaders/DRACOLoader.js +5 -5
  69. package/examples/jsm/loaders/EXRLoader.js +687 -48
  70. package/examples/jsm/loaders/FBXLoader.js +235 -37
  71. package/examples/jsm/loaders/GCodeLoader.js +34 -8
  72. package/examples/jsm/loaders/GLTFLoader.js +146 -178
  73. package/examples/jsm/loaders/HDRLoader.js +1 -2
  74. package/examples/jsm/loaders/KMZLoader.js +5 -5
  75. package/examples/jsm/loaders/KTX2Loader.js +27 -5
  76. package/examples/jsm/loaders/LDrawLoader.js +41 -50
  77. package/examples/jsm/loaders/LWOLoader.js +7 -39
  78. package/examples/jsm/loaders/NRRDLoader.js +2 -2
  79. package/examples/jsm/loaders/PCDLoader.js +4 -2
  80. package/examples/jsm/loaders/SVGLoader.js +2 -2
  81. package/examples/jsm/loaders/TDSLoader.js +0 -2
  82. package/examples/jsm/loaders/TGALoader.js +0 -2
  83. package/examples/jsm/loaders/USDLoader.js +100 -40
  84. package/examples/jsm/loaders/UltraHDRLoader.js +285 -160
  85. package/examples/jsm/loaders/VOXLoader.js +660 -117
  86. package/examples/jsm/loaders/VRMLLoader.js +79 -2
  87. package/examples/jsm/loaders/VTKLoader.js +42 -25
  88. package/examples/jsm/loaders/collada/ColladaComposer.js +3044 -0
  89. package/examples/jsm/loaders/collada/ColladaParser.js +1977 -0
  90. package/examples/jsm/loaders/usd/USDAParser.js +450 -363
  91. package/examples/jsm/loaders/usd/USDCParser.js +1867 -6
  92. package/examples/jsm/loaders/usd/USDComposer.js +4594 -0
  93. package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +2 -2
  94. package/examples/jsm/materials/WoodNodeMaterial.js +11 -11
  95. package/examples/jsm/math/Octree.js +131 -1
  96. package/examples/jsm/misc/GPUComputationRenderer.js +2 -0
  97. package/examples/jsm/misc/RollerCoaster.js +42 -4
  98. package/examples/jsm/misc/Volume.js +0 -1
  99. package/examples/jsm/misc/VolumeSlice.js +0 -1
  100. package/examples/jsm/modifiers/TessellateModifier.js +1 -1
  101. package/examples/jsm/objects/LensflareMesh.js +1 -1
  102. package/examples/jsm/objects/Reflector.js +73 -25
  103. package/examples/jsm/objects/Sky.js +90 -6
  104. package/examples/jsm/objects/SkyMesh.js +150 -16
  105. package/examples/jsm/objects/Water.js +4 -3
  106. package/examples/jsm/objects/Water2.js +5 -3
  107. package/examples/jsm/objects/WaterMesh.js +5 -7
  108. package/examples/jsm/physics/AmmoPhysics.js +12 -7
  109. package/examples/jsm/physics/JoltPhysics.js +10 -6
  110. package/examples/jsm/physics/RapierPhysics.js +9 -5
  111. package/examples/jsm/postprocessing/EffectComposer.js +7 -5
  112. package/examples/jsm/postprocessing/OutputPass.js +9 -0
  113. package/examples/jsm/postprocessing/RenderPass.js +10 -0
  114. package/examples/jsm/postprocessing/RenderTransitionPass.js +1 -1
  115. package/examples/jsm/postprocessing/UnrealBloomPass.js +48 -18
  116. package/examples/jsm/renderers/CSS3DRenderer.js +1 -1
  117. package/examples/jsm/renderers/Projector.js +246 -28
  118. package/examples/jsm/renderers/SVGRenderer.js +174 -60
  119. package/examples/jsm/shaders/GTAOShader.js +19 -6
  120. package/examples/jsm/shaders/HalftoneShader.js +12 -1
  121. package/examples/jsm/shaders/PoissonDenoiseShader.js +6 -2
  122. package/examples/jsm/shaders/SAOShader.js +17 -4
  123. package/examples/jsm/shaders/SSAOShader.js +11 -1
  124. package/examples/jsm/shaders/SSRShader.js +6 -5
  125. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +2 -4
  126. package/examples/jsm/shaders/VignetteShader.js +1 -1
  127. package/examples/jsm/transpiler/AST.js +44 -0
  128. package/examples/jsm/transpiler/GLSLDecoder.js +63 -6
  129. package/examples/jsm/transpiler/ShaderToyDecoder.js +2 -0
  130. package/examples/jsm/transpiler/TSLEncoder.js +46 -3
  131. package/examples/jsm/transpiler/TranspilerUtils.js +3 -3
  132. package/examples/jsm/transpiler/WGSLEncoder.js +27 -0
  133. package/examples/jsm/tsl/WebGLNodesHandler.js +605 -0
  134. package/examples/jsm/tsl/display/AfterImageNode.js +11 -1
  135. package/examples/jsm/tsl/display/AnaglyphPassNode.js +458 -16
  136. package/examples/jsm/tsl/display/AnamorphicNode.js +12 -1
  137. package/examples/jsm/tsl/display/BilateralBlurNode.js +374 -0
  138. package/examples/jsm/tsl/display/BloomNode.js +16 -6
  139. package/examples/jsm/tsl/display/CRT.js +150 -0
  140. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +3 -36
  141. package/examples/jsm/tsl/display/DenoiseNode.js +1 -1
  142. package/examples/jsm/tsl/display/DepthOfFieldNode.js +1 -1
  143. package/examples/jsm/tsl/display/DotScreenNode.js +1 -1
  144. package/examples/jsm/tsl/display/FSR1Node.js +477 -0
  145. package/examples/jsm/tsl/display/FXAANode.js +2 -2
  146. package/examples/jsm/tsl/display/GTAONode.js +6 -4
  147. package/examples/jsm/tsl/display/GaussianBlurNode.js +21 -2
  148. package/examples/jsm/tsl/display/GodraysNode.js +615 -0
  149. package/examples/jsm/tsl/display/LensflareNode.js +1 -1
  150. package/examples/jsm/tsl/display/Lut3DNode.js +1 -1
  151. package/examples/jsm/tsl/display/OutlineNode.js +69 -19
  152. package/examples/jsm/tsl/display/ParallaxBarrierPassNode.js +2 -2
  153. package/examples/jsm/tsl/display/PixelationPassNode.js +7 -6
  154. package/examples/jsm/tsl/display/RGBShiftNode.js +2 -2
  155. package/examples/jsm/tsl/display/RetroPassNode.js +263 -0
  156. package/examples/jsm/tsl/display/SMAANode.js +2 -2
  157. package/examples/jsm/tsl/display/SSAAPassNode.js +2 -2
  158. package/examples/jsm/tsl/display/SSGINode.js +8 -24
  159. package/examples/jsm/tsl/display/SSRNode.js +8 -8
  160. package/examples/jsm/tsl/display/SSSNode.js +6 -4
  161. package/examples/jsm/tsl/display/Shape.js +29 -0
  162. package/examples/jsm/tsl/display/SharpenNode.js +283 -0
  163. package/examples/jsm/tsl/display/SobelOperatorNode.js +2 -2
  164. package/examples/jsm/tsl/display/StereoCompositePassNode.js +8 -1
  165. package/examples/jsm/tsl/display/StereoPassNode.js +1 -2
  166. package/examples/jsm/tsl/display/TAAUNode.js +835 -0
  167. package/examples/jsm/tsl/display/TRAANode.js +315 -126
  168. package/examples/jsm/tsl/display/TransitionNode.js +1 -1
  169. package/examples/jsm/tsl/display/depthAwareBlend.js +80 -0
  170. package/examples/jsm/tsl/display/radialBlur.js +68 -0
  171. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +300 -0
  172. package/examples/jsm/tsl/lighting/data/AmbientLightDataNode.js +61 -0
  173. package/examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js +111 -0
  174. package/examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js +99 -0
  175. package/examples/jsm/tsl/lighting/data/PointLightDataNode.js +134 -0
  176. package/examples/jsm/tsl/lighting/data/SpotLightDataNode.js +161 -0
  177. package/examples/jsm/tsl/math/Bayer.js +53 -3
  178. package/examples/jsm/utils/BufferGeometryUtils.js +2 -3
  179. package/examples/jsm/utils/ColorUtils.js +76 -0
  180. package/examples/jsm/utils/LDrawUtils.js +1 -1
  181. package/examples/jsm/utils/ShadowMapViewer.js +24 -10
  182. package/examples/jsm/utils/ShadowMapViewerGPU.js +1 -1
  183. package/examples/jsm/utils/SkeletonUtils.js +14 -8
  184. package/examples/jsm/utils/WebGPUTextureUtils.js +1 -1
  185. package/examples/jsm/webxr/XRHandMeshModel.js +36 -10
  186. package/examples/jsm/webxr/XRHandModelFactory.js +2 -1
  187. package/package.json +24 -30
  188. package/src/Three.Core.js +3 -1
  189. package/src/Three.TSL.js +25 -11
  190. package/src/Three.WebGPU.Nodes.js +5 -0
  191. package/src/Three.WebGPU.js +9 -0
  192. package/src/Three.js +1 -0
  193. package/src/animation/AnimationAction.js +12 -2
  194. package/src/animation/AnimationClip.js +1 -1
  195. package/src/animation/AnimationMixer.js +6 -0
  196. package/src/animation/AnimationUtils.js +1 -12
  197. package/src/animation/KeyframeTrack.js +47 -8
  198. package/src/animation/PropertyMixer.js +4 -4
  199. package/src/animation/tracks/BooleanKeyframeTrack.js +1 -1
  200. package/src/animation/tracks/ColorKeyframeTrack.js +1 -1
  201. package/src/animation/tracks/NumberKeyframeTrack.js +1 -1
  202. package/src/animation/tracks/QuaternionKeyframeTrack.js +1 -1
  203. package/src/animation/tracks/StringKeyframeTrack.js +1 -1
  204. package/src/animation/tracks/VectorKeyframeTrack.js +1 -1
  205. package/src/audio/Audio.js +1 -1
  206. package/src/audio/AudioContext.js +2 -2
  207. package/src/audio/AudioListener.js +5 -3
  208. package/src/cameras/Camera.js +32 -2
  209. package/src/cameras/CubeCamera.js +20 -0
  210. package/src/constants.js +90 -5
  211. package/src/core/BufferAttribute.js +13 -1
  212. package/src/core/BufferGeometry.js +14 -2
  213. package/src/core/Clock.js +7 -0
  214. package/src/core/Object3D.js +52 -4
  215. package/src/core/Raycaster.js +2 -2
  216. package/src/core/RenderTarget.js +4 -4
  217. package/src/extras/PMREMGenerator.js +7 -18
  218. package/src/extras/TextureUtils.js +5 -1
  219. package/src/extras/curves/CatmullRomCurve3.js +3 -2
  220. package/src/geometries/ExtrudeGeometry.js +2 -2
  221. package/src/geometries/PolyhedronGeometry.js +1 -1
  222. package/src/geometries/TorusGeometry.js +8 -3
  223. package/src/helpers/CameraHelper.js +3 -0
  224. package/src/helpers/DirectionalLightHelper.js +4 -1
  225. package/src/helpers/HemisphereLightHelper.js +3 -0
  226. package/src/helpers/PointLightHelper.js +1 -25
  227. package/src/helpers/SpotLightHelper.js +3 -0
  228. package/src/lights/DirectionalLight.js +13 -0
  229. package/src/lights/HemisphereLight.js +10 -0
  230. package/src/lights/Light.js +1 -11
  231. package/src/lights/LightProbe.js +0 -15
  232. package/src/lights/LightShadow.js +15 -6
  233. package/src/lights/PointLight.js +15 -0
  234. package/src/lights/PointLightShadow.js +0 -86
  235. package/src/lights/SpotLight.js +22 -1
  236. package/src/lights/webgpu/IESSpotLight.js +2 -1
  237. package/src/loaders/AudioLoader.js +11 -1
  238. package/src/loaders/Cache.js +28 -0
  239. package/src/loaders/DataTextureLoader.js +6 -4
  240. package/src/loaders/FileLoader.js +2 -3
  241. package/src/loaders/ImageBitmapLoader.js +12 -9
  242. package/src/loaders/Loader.js +6 -0
  243. package/src/loaders/MaterialLoader.js +3 -2
  244. package/src/loaders/ObjectLoader.js +46 -6
  245. package/src/loaders/nodes/NodeLoader.js +2 -2
  246. package/src/loaders/nodes/NodeObjectLoader.js +18 -0
  247. package/src/materials/Material.js +2 -0
  248. package/src/materials/MeshLambertMaterial.js +9 -0
  249. package/src/materials/MeshPhongMaterial.js +9 -0
  250. package/src/materials/MeshToonMaterial.js +1 -1
  251. package/src/materials/ShaderMaterial.js +20 -1
  252. package/src/materials/nodes/Line2NodeMaterial.js +34 -7
  253. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +5 -2
  254. package/src/materials/nodes/MeshStandardNodeMaterial.js +5 -4
  255. package/src/materials/nodes/NodeMaterial.js +45 -25
  256. package/src/materials/nodes/manager/NodeMaterialObserver.js +191 -86
  257. package/src/math/Line3.js +6 -5
  258. package/src/math/MathUtils.js +10 -10
  259. package/src/math/Matrix2.js +13 -9
  260. package/src/math/Matrix3.js +13 -9
  261. package/src/math/Matrix4.js +87 -74
  262. package/src/math/Plane.js +4 -3
  263. package/src/math/Quaternion.js +3 -29
  264. package/src/math/Sphere.js +1 -1
  265. package/src/math/Triangle.js +1 -1
  266. package/src/math/Vector2.js +11 -7
  267. package/src/math/Vector3.js +15 -13
  268. package/src/math/Vector4.js +13 -9
  269. package/src/math/interpolants/BezierInterpolant.js +108 -0
  270. package/src/nodes/Nodes.js +86 -68
  271. package/src/nodes/TSL.js +7 -7
  272. package/src/nodes/accessors/Arrays.js +1 -1
  273. package/src/nodes/accessors/BatchNode.js +10 -10
  274. package/src/nodes/accessors/Bitangent.js +5 -5
  275. package/src/nodes/accessors/BufferAttributeNode.js +107 -15
  276. package/src/nodes/accessors/BufferNode.js +29 -2
  277. package/src/nodes/accessors/Camera.js +149 -28
  278. package/src/nodes/accessors/ClippingNode.js +4 -4
  279. package/src/nodes/accessors/CubeTextureNode.js +27 -2
  280. package/src/nodes/accessors/InstanceNode.js +148 -43
  281. package/src/nodes/accessors/MaterialNode.js +9 -1
  282. package/src/nodes/accessors/MaterialProperties.js +2 -5
  283. package/src/nodes/accessors/MaterialReferenceNode.js +1 -2
  284. package/src/nodes/accessors/ModelNode.js +1 -1
  285. package/src/nodes/accessors/Normal.js +11 -11
  286. package/src/nodes/accessors/Object3DNode.js +1 -1
  287. package/src/nodes/accessors/Position.js +34 -2
  288. package/src/nodes/accessors/ReferenceBaseNode.js +6 -6
  289. package/src/nodes/accessors/ReferenceNode.js +8 -8
  290. package/src/nodes/accessors/RendererReferenceNode.js +1 -2
  291. package/src/nodes/accessors/SceneProperties.js +47 -0
  292. package/src/nodes/accessors/SkinningNode.js +27 -26
  293. package/src/nodes/accessors/StorageBufferNode.js +14 -25
  294. package/src/nodes/accessors/StorageTextureNode.js +40 -9
  295. package/src/nodes/accessors/Tangent.js +4 -14
  296. package/src/nodes/accessors/Texture3DNode.js +32 -35
  297. package/src/nodes/accessors/TextureNode.js +67 -23
  298. package/src/nodes/accessors/UniformArrayNode.js +6 -4
  299. package/src/nodes/accessors/UserDataNode.js +1 -2
  300. package/src/nodes/accessors/VertexColorNode.js +1 -2
  301. package/src/nodes/code/FunctionCallNode.js +1 -1
  302. package/src/nodes/code/FunctionNode.js +2 -3
  303. package/src/nodes/core/ArrayNode.js +21 -2
  304. package/src/nodes/core/AssignNode.js +3 -3
  305. package/src/nodes/core/AttributeNode.js +3 -3
  306. package/src/nodes/core/BypassNode.js +1 -1
  307. package/src/nodes/core/ContextNode.js +104 -5
  308. package/src/nodes/core/IndexNode.js +2 -1
  309. package/src/nodes/core/InputNode.js +1 -1
  310. package/src/nodes/core/InspectorNode.js +1 -1
  311. package/src/nodes/core/IsolateNode.js +1 -1
  312. package/src/nodes/core/MRTNode.js +48 -2
  313. package/src/nodes/core/Node.js +112 -15
  314. package/src/nodes/core/NodeBuilder.js +284 -66
  315. package/src/nodes/core/NodeError.js +28 -0
  316. package/src/nodes/core/NodeFrame.js +12 -4
  317. package/src/nodes/core/NodeUtils.js +11 -9
  318. package/src/nodes/core/OutputStructNode.js +12 -10
  319. package/src/nodes/core/ParameterNode.js +4 -4
  320. package/src/nodes/core/PropertyNode.js +19 -3
  321. package/src/nodes/core/StackNode.js +66 -17
  322. package/src/nodes/core/StackTrace.js +139 -0
  323. package/src/nodes/core/StructNode.js +17 -3
  324. package/src/nodes/core/StructTypeNode.js +12 -18
  325. package/src/nodes/core/SubBuildNode.js +2 -2
  326. package/src/nodes/core/UniformGroupNode.js +36 -6
  327. package/src/nodes/core/UniformNode.js +21 -5
  328. package/src/nodes/core/VarNode.js +48 -23
  329. package/src/nodes/core/VaryingNode.js +2 -19
  330. package/src/nodes/display/BlendModes.js +0 -64
  331. package/src/nodes/display/ColorAdjustment.js +17 -0
  332. package/src/nodes/display/ColorSpaceNode.js +3 -3
  333. package/src/nodes/display/NormalMapNode.js +39 -4
  334. package/src/nodes/display/PassNode.js +125 -16
  335. package/src/nodes/display/RenderOutputNode.js +7 -7
  336. package/src/nodes/display/ScreenNode.js +4 -2
  337. package/src/nodes/display/ToneMappingNode.js +1 -1
  338. package/src/nodes/display/ToonOutlinePassNode.js +2 -2
  339. package/src/nodes/display/ViewportDepthNode.js +52 -4
  340. package/src/nodes/display/ViewportDepthTextureNode.js +11 -15
  341. package/src/nodes/display/ViewportTextureNode.js +39 -11
  342. package/src/nodes/fog/Fog.js +18 -35
  343. package/src/nodes/functions/BSDF/BRDF_GGX_Multiscatter.js +3 -3
  344. package/src/nodes/functions/BSDF/DFGLUT.js +56 -0
  345. package/src/nodes/functions/BSDF/EnvironmentBRDF.js +2 -2
  346. package/src/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +2 -2
  347. package/src/nodes/functions/PhysicalLightingModel.js +126 -45
  348. package/src/nodes/geometry/RangeNode.js +5 -3
  349. package/src/nodes/gpgpu/AtomicFunctionNode.js +1 -1
  350. package/src/nodes/gpgpu/BarrierNode.js +9 -0
  351. package/src/nodes/gpgpu/ComputeBuiltinNode.js +2 -3
  352. package/src/nodes/gpgpu/ComputeNode.js +74 -48
  353. package/src/nodes/gpgpu/SubgroupFunctionNode.js +2 -2
  354. package/src/nodes/gpgpu/WorkgroupInfoNode.js +4 -4
  355. package/src/nodes/lighting/AnalyticLightNode.js +53 -0
  356. package/src/nodes/lighting/EnvironmentNode.js +28 -3
  357. package/src/nodes/lighting/LightsNode.js +7 -28
  358. package/src/nodes/lighting/PointShadowNode.js +162 -149
  359. package/src/nodes/lighting/ShadowFilterNode.js +53 -65
  360. package/src/nodes/lighting/ShadowNode.js +120 -42
  361. package/src/nodes/math/BitcastNode.js +1 -1
  362. package/src/nodes/math/BitcountNode.js +433 -0
  363. package/src/nodes/math/ConditionalNode.js +3 -3
  364. package/src/nodes/math/MathNode.js +76 -41
  365. package/src/nodes/math/OperatorNode.js +3 -2
  366. package/src/nodes/math/PackFloatNode.js +98 -0
  367. package/src/nodes/math/UnpackFloatNode.js +96 -0
  368. package/src/nodes/pmrem/PMREMNode.js +1 -1
  369. package/src/nodes/pmrem/PMREMUtils.js +9 -15
  370. package/src/nodes/tsl/TSLBase.js +1 -1
  371. package/src/nodes/tsl/TSLCore.js +38 -17
  372. package/src/nodes/utils/ArrayElementNode.js +14 -1
  373. package/src/nodes/utils/ConvertNode.js +1 -1
  374. package/src/nodes/utils/DebugNode.js +12 -12
  375. package/src/nodes/utils/EventNode.js +31 -2
  376. package/src/nodes/utils/FlipNode.js +1 -1
  377. package/src/nodes/utils/FunctionOverloadingNode.js +1 -1
  378. package/src/nodes/utils/JoinNode.js +3 -3
  379. package/src/nodes/utils/LoopNode.js +1 -1
  380. package/src/nodes/utils/MemberNode.js +2 -2
  381. package/src/nodes/utils/Packing.js +13 -1
  382. package/src/nodes/utils/PostProcessingUtils.js +33 -1
  383. package/src/nodes/utils/RTTNode.js +1 -1
  384. package/src/nodes/utils/ReflectorNode.js +3 -4
  385. package/src/nodes/utils/Remap.js +48 -0
  386. package/src/nodes/utils/RotateNode.js +1 -1
  387. package/src/nodes/utils/SampleNode.js +1 -1
  388. package/src/nodes/utils/SetNode.js +1 -1
  389. package/src/nodes/utils/SplitNode.js +1 -1
  390. package/src/nodes/utils/SpriteSheetUV.js +35 -0
  391. package/src/nodes/utils/UVUtils.js +28 -0
  392. package/src/objects/BatchedMesh.js +44 -16
  393. package/src/objects/InstancedMesh.js +30 -3
  394. package/src/objects/Line.js +1 -1
  395. package/src/objects/Mesh.js +1 -1
  396. package/src/objects/Points.js +1 -1
  397. package/src/objects/Skeleton.js +9 -0
  398. package/src/objects/SkinnedMesh.js +26 -9
  399. package/src/renderers/WebGLRenderer.js +329 -145
  400. package/src/renderers/common/Animation.js +3 -3
  401. package/src/renderers/common/Attributes.js +15 -1
  402. package/src/renderers/common/Backend.js +29 -8
  403. package/src/renderers/common/Background.js +26 -13
  404. package/src/renderers/common/BindGroup.js +1 -16
  405. package/src/renderers/common/Binding.js +11 -0
  406. package/src/renderers/common/Bindings.js +29 -14
  407. package/src/renderers/common/BlendMode.js +143 -0
  408. package/src/renderers/common/Buffer.js +40 -0
  409. package/src/renderers/common/BundleGroup.js +1 -1
  410. package/src/renderers/common/ChainMap.js +30 -6
  411. package/src/renderers/common/ComputePipeline.js +1 -1
  412. package/src/renderers/common/CubeRenderTarget.js +51 -7
  413. package/src/renderers/common/Geometries.js +29 -3
  414. package/src/renderers/common/Info.js +333 -4
  415. package/src/renderers/common/InspectorBase.js +6 -1
  416. package/src/renderers/common/Lighting.js +5 -21
  417. package/src/renderers/common/Pipelines.js +40 -7
  418. package/src/renderers/common/PostProcessing.js +8 -206
  419. package/src/renderers/common/ReadbackBuffer.js +78 -0
  420. package/src/renderers/common/RenderBundle.js +3 -1
  421. package/src/renderers/common/RenderBundles.js +7 -3
  422. package/src/renderers/common/RenderContext.js +16 -0
  423. package/src/renderers/common/RenderContexts.js +33 -49
  424. package/src/renderers/common/RenderLists.js +2 -1
  425. package/src/renderers/common/RenderObject.js +17 -5
  426. package/src/renderers/common/RenderObjectPipeline.js +40 -0
  427. package/src/renderers/common/RenderObjects.js +21 -5
  428. package/src/renderers/common/RenderPipeline.js +232 -17
  429. package/src/renderers/common/Renderer.js +481 -117
  430. package/src/renderers/common/Sampler.js +4 -4
  431. package/src/renderers/common/StorageBuffer.js +13 -1
  432. package/src/renderers/common/Textures.js +89 -4
  433. package/src/renderers/common/TimestampQueryPool.js +5 -3
  434. package/src/renderers/common/Uniform.js +8 -0
  435. package/src/renderers/common/UniformsGroup.js +62 -1
  436. package/src/renderers/common/XRManager.js +37 -29
  437. package/src/renderers/common/extras/PMREMGenerator.js +25 -23
  438. package/src/renderers/common/nodes/NodeBuilderState.js +1 -1
  439. package/src/renderers/common/nodes/{Nodes.js → NodeManager.js} +242 -99
  440. package/src/renderers/common/nodes/NodeStorageBuffer.js +13 -2
  441. package/src/renderers/common/nodes/NodeUniformBuffer.js +52 -0
  442. package/src/renderers/shaders/DFGLUTData.js +19 -34
  443. package/src/renderers/shaders/ShaderChunk/batching_pars_vertex.glsl.js +2 -2
  444. package/src/renderers/shaders/ShaderChunk/color_fragment.glsl.js +1 -5
  445. package/src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl.js +1 -5
  446. package/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js +1 -5
  447. package/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js +8 -10
  448. package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +0 -1
  449. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +8 -12
  450. package/src/renderers/shaders/ShaderChunk/lightprobes_pars_fragment.glsl.js +80 -0
  451. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +13 -2
  452. package/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js +6 -0
  453. package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +6 -2
  454. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +2 -0
  455. package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +8 -4
  456. package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +112 -53
  457. package/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js +7 -0
  458. package/src/renderers/shaders/ShaderChunk/packing.glsl.js +20 -4
  459. package/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js +0 -1
  460. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +225 -186
  461. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +12 -2
  462. package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +1 -1
  463. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +1 -1
  464. package/src/renderers/shaders/ShaderChunk.js +5 -3
  465. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +1 -2
  466. package/src/renderers/shaders/ShaderLib/depth.glsl.js +3 -0
  467. package/src/renderers/shaders/ShaderLib/{distanceRGBA.glsl.js → distance.glsl.js} +1 -2
  468. package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +2 -1
  469. package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +1 -2
  470. package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +2 -1
  471. package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -9
  472. package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +0 -1
  473. package/src/renderers/shaders/ShaderLib/shadow.glsl.js +1 -1
  474. package/src/renderers/shaders/ShaderLib/vsm.glsl.js +4 -6
  475. package/src/renderers/shaders/ShaderLib.js +7 -6
  476. package/src/renderers/shaders/UniformsLib.js +7 -5
  477. package/src/renderers/shaders/UniformsUtils.js +27 -5
  478. package/src/renderers/webgl/WebGLAnimation.js +2 -1
  479. package/src/renderers/webgl/WebGLBackground.js +15 -15
  480. package/src/renderers/webgl/WebGLBindingStates.js +99 -27
  481. package/src/renderers/webgl/WebGLBufferRenderer.js +0 -32
  482. package/src/renderers/webgl/WebGLCapabilities.js +9 -4
  483. package/src/renderers/webgl/WebGLEnvironments.js +228 -0
  484. package/src/renderers/webgl/WebGLGeometries.js +10 -7
  485. package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +0 -32
  486. package/src/renderers/webgl/WebGLLights.js +18 -1
  487. package/src/renderers/webgl/WebGLMaterials.js +24 -13
  488. package/src/renderers/webgl/WebGLObjects.js +3 -1
  489. package/src/renderers/webgl/WebGLOutput.js +270 -0
  490. package/src/renderers/webgl/WebGLProgram.js +49 -109
  491. package/src/renderers/webgl/WebGLPrograms.js +63 -51
  492. package/src/renderers/webgl/WebGLRenderLists.js +15 -0
  493. package/src/renderers/webgl/WebGLRenderStates.js +13 -2
  494. package/src/renderers/webgl/WebGLShadowMap.js +188 -24
  495. package/src/renderers/webgl/WebGLState.js +75 -37
  496. package/src/renderers/webgl/WebGLTextures.js +215 -54
  497. package/src/renderers/webgl/WebGLUniforms.js +40 -3
  498. package/src/renderers/webgl/WebGLUniformsGroups.js +19 -0
  499. package/src/renderers/webgl/WebGLUtils.js +6 -2
  500. package/src/renderers/webgl-fallback/WebGLBackend.js +253 -82
  501. package/src/renderers/webgl-fallback/WebGLBufferRenderer.js +0 -41
  502. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +173 -74
  503. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +53 -19
  504. package/src/renderers/webgl-fallback/utils/WebGLCapabilities.js +25 -0
  505. package/src/renderers/webgl-fallback/utils/WebGLState.js +223 -6
  506. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +68 -53
  507. package/src/renderers/webgl-fallback/utils/WebGLTimestampQueryPool.js +10 -10
  508. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +6 -2
  509. package/src/renderers/webgpu/WebGPUBackend.js +260 -140
  510. package/src/renderers/webgpu/WebGPURenderer.js +2 -1
  511. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +366 -90
  512. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +107 -34
  513. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +357 -200
  514. package/src/renderers/webgpu/utils/WebGPUCapabilities.js +48 -0
  515. package/src/renderers/webgpu/utils/WebGPUConstants.js +10 -0
  516. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +61 -23
  517. package/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +152 -200
  518. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +156 -59
  519. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +7 -7
  520. package/src/renderers/webgpu/utils/WebGPUUtils.js +33 -11
  521. package/src/renderers/webxr/WebXRController.js +12 -0
  522. package/src/renderers/webxr/WebXRManager.js +4 -2
  523. package/src/textures/CubeDepthTexture.js +76 -0
  524. package/src/textures/HTMLTexture.js +74 -0
  525. package/src/textures/Source.js +2 -2
  526. package/src/textures/Texture.js +16 -5
  527. package/src/utils.js +280 -3
  528. package/examples/jsm/materials/MeshGouraudMaterial.js +0 -434
  529. package/examples/jsm/materials/MeshPostProcessingMaterial.js +0 -167
  530. package/examples/jsm/shaders/GodRaysShader.js +0 -333
  531. package/src/nodes/accessors/SceneNode.js +0 -145
  532. package/src/nodes/code/ScriptableNode.js +0 -726
  533. package/src/nodes/code/ScriptableValueNode.js +0 -253
  534. package/src/nodes/display/PosterizeNode.js +0 -65
  535. package/src/nodes/functions/BSDF/DFGApprox.js +0 -71
  536. package/src/nodes/utils/RemapNode.js +0 -125
  537. package/src/nodes/utils/SpriteSheetUVNode.js +0 -90
  538. package/src/renderers/webgl/WebGLCubeMaps.js +0 -99
  539. package/src/renderers/webgl/WebGLCubeUVMaps.js +0 -134
@@ -1,23 +1,15 @@
1
- import {
2
- BufferAttribute,
3
- BufferGeometry,
4
- ClampToEdgeWrapping,
5
- Group,
6
- NoColorSpace,
7
- Mesh,
8
- MeshPhysicalMaterial,
9
- MirroredRepeatWrapping,
10
- RepeatWrapping,
11
- SRGBColorSpace,
12
- TextureLoader,
13
- Object3D,
14
- Vector2
15
- } from 'three';
1
+ // Pre-compiled regex patterns for performance
2
+ const DEF_MATCH_REGEX = /^def\s+(?:(\w+)\s+)?"?([^"]+)"?$/;
3
+ const VARIANT_STRING_REGEX = /^string\s+(\w+)$/;
4
+ const ATTR_MATCH_REGEX = /^(?:uniform\s+)?(\w+(?:\[\])?)\s+(.+)$/;
16
5
 
17
6
  class USDAParser {
18
7
 
19
8
  parseText( text ) {
20
9
 
10
+ // Preprocess: strip comments and normalize multiline values
11
+ text = this._preprocess( text );
12
+
21
13
  const root = {};
22
14
 
23
15
  const lines = text.split( '\n' );
@@ -27,18 +19,22 @@ class USDAParser {
27
19
 
28
20
  const stack = [ root ];
29
21
 
30
- // Parse USDA file
31
-
32
22
  for ( const line of lines ) {
33
23
 
34
- // console.log( line );
35
-
36
24
  if ( line.includes( '=' ) ) {
37
25
 
38
- const assignment = line.split( '=' );
26
+ // Find the first '=' that's not inside quotes
27
+ const eqIdx = this._findAssignmentOperator( line );
28
+
29
+ if ( eqIdx === - 1 ) {
30
+
31
+ string = line.trim();
32
+ continue;
39
33
 
40
- const lhs = assignment[ 0 ].trim();
41
- const rhs = assignment[ 1 ].trim();
34
+ }
35
+
36
+ const lhs = line.slice( 0, eqIdx ).trim();
37
+ const rhs = line.slice( eqIdx + 1 ).trim();
42
38
 
43
39
  if ( rhs.endsWith( '{' ) ) {
44
40
 
@@ -66,6 +62,20 @@ class USDAParser {
66
62
 
67
63
  }
68
64
 
65
+ } else if ( line.includes( ':' ) && ! line.includes( '=' ) ) {
66
+
67
+ // Handle dictionary entries like "0: [(...)...]" for timeSamples
68
+ const colonIdx = line.indexOf( ':' );
69
+ const key = line.slice( 0, colonIdx ).trim();
70
+ const value = line.slice( colonIdx + 1 ).trim();
71
+
72
+ // Only process if key looks like a number (timeSamples frame)
73
+ if ( /^[\d.]+$/.test( key ) ) {
74
+
75
+ target[ key ] = value;
76
+
77
+ }
78
+
69
79
  } else if ( line.endsWith( '{' ) ) {
70
80
 
71
81
  const group = target[ string ] || {};
@@ -98,7 +108,7 @@ class USDAParser {
98
108
 
99
109
  target = stack[ stack.length - 1 ];
100
110
 
101
- } else {
111
+ } else if ( line.trim() ) {
102
112
 
103
113
  string = line.trim();
104
114
 
@@ -110,629 +120,706 @@ class USDAParser {
110
120
 
111
121
  }
112
122
 
113
- parse( text, assets ) {
123
+ _preprocess( text ) {
114
124
 
115
- const root = this.parseText( text );
125
+ // Remove block comments /* ... */
126
+ text = this._stripBlockComments( text );
116
127
 
117
- // Build scene graph
128
+ // Collapse triple-quoted strings into single lines
129
+ text = this._collapseTripleQuotedStrings( text );
118
130
 
119
- function findMeshGeometry( data ) {
120
-
121
- if ( ! data ) return undefined;
131
+ // Remove line comments # ... (but preserve #usda header)
132
+ // Only remove # comments that aren't at the start of a line or after whitespace
133
+ const lines = text.split( '\n' );
134
+ const processed = [];
122
135
 
123
- if ( 'prepend references' in data ) {
136
+ let inMultilineValue = false;
137
+ let bracketDepth = 0;
138
+ let parenDepth = 0;
139
+ let accumulated = '';
124
140
 
125
- const reference = data[ 'prepend references' ];
126
- const parts = reference.split( '@' );
127
- const path = parts[ 1 ].replace( /^.\//, '' );
128
- const id = parts[ 2 ].replace( /^<\//, '' ).replace( />$/, '' );
141
+ for ( let i = 0; i < lines.length; i ++ ) {
129
142
 
130
- return findGeometry( assets[ path ], id );
143
+ let line = lines[ i ];
131
144
 
132
- }
145
+ // Strip inline comments (but not inside strings)
146
+ line = this._stripInlineComment( line );
133
147
 
134
- return findGeometry( data );
148
+ // Track bracket/paren depth for multiline values
149
+ const trimmed = line.trim();
135
150
 
136
- }
151
+ if ( inMultilineValue ) {
137
152
 
138
- function findGeometry( data, id ) {
153
+ // Continue accumulating multiline value
154
+ accumulated += ' ' + trimmed;
139
155
 
140
- if ( ! data ) return undefined;
156
+ // Update depths
157
+ for ( const ch of trimmed ) {
141
158
 
142
- if ( id !== undefined ) {
159
+ if ( ch === '[' ) bracketDepth ++;
160
+ else if ( ch === ']' ) bracketDepth --;
161
+ else if ( ch === '(' && bracketDepth > 0 ) parenDepth ++;
162
+ else if ( ch === ')' && bracketDepth > 0 ) parenDepth --;
143
163
 
144
- const def = `def Mesh "${id}"`;
164
+ }
145
165
 
146
- if ( def in data ) {
166
+ // Check if multiline value is complete
167
+ if ( bracketDepth === 0 && parenDepth === 0 ) {
147
168
 
148
- return data[ def ];
169
+ processed.push( accumulated );
170
+ accumulated = '';
171
+ inMultilineValue = false;
149
172
 
150
173
  }
151
174
 
152
- }
153
-
154
- for ( const name in data ) {
175
+ } else {
155
176
 
156
- const object = data[ name ];
177
+ // Check if this line starts a multiline array value
178
+ // Look for patterns like "attr = [" or "attr = @path@[" without closing ]
179
+ if ( trimmed.includes( '=' ) ) {
157
180
 
158
- if ( name.startsWith( 'def Mesh' ) ) {
181
+ const eqIdx = this._findAssignmentOperator( trimmed );
159
182
 
160
- return object;
183
+ if ( eqIdx !== - 1 ) {
161
184
 
162
- }
185
+ const rhs = trimmed.slice( eqIdx + 1 ).trim();
163
186
 
187
+ // Count brackets in the value part
188
+ let openBrackets = 0;
189
+ let closeBrackets = 0;
164
190
 
165
- if ( typeof object === 'object' ) {
191
+ for ( const ch of rhs ) {
166
192
 
167
- const geometry = findGeometry( object );
193
+ if ( ch === '[' ) openBrackets ++;
194
+ else if ( ch === ']' ) closeBrackets ++;
168
195
 
169
- if ( geometry ) return geometry;
196
+ }
170
197
 
171
- }
198
+ if ( openBrackets > closeBrackets ) {
172
199
 
173
- }
200
+ // Multiline array detected
201
+ inMultilineValue = true;
202
+ bracketDepth = openBrackets - closeBrackets;
203
+ parenDepth = 0;
204
+ accumulated = trimmed;
205
+ continue;
174
206
 
175
- }
207
+ }
176
208
 
177
- function buildGeometry( data ) {
209
+ }
178
210
 
179
- if ( ! data ) return undefined;
211
+ }
180
212
 
181
- const geometry = new BufferGeometry();
182
- let indices = null;
183
- let counts = null;
184
- let uvs = null;
213
+ processed.push( trimmed );
185
214
 
186
- let positionsLength = - 1;
215
+ }
187
216
 
188
- // index
217
+ }
189
218
 
190
- if ( 'int[] faceVertexIndices' in data ) {
219
+ return processed.join( '\n' );
191
220
 
192
- indices = JSON.parse( data[ 'int[] faceVertexIndices' ] );
221
+ }
193
222
 
194
- }
223
+ _stripBlockComments( text ) {
195
224
 
196
- // face count
225
+ // Iteratively remove /* ... */ comments without regex backtracking
226
+ let result = '';
227
+ let i = 0;
197
228
 
198
- if ( 'int[] faceVertexCounts' in data ) {
229
+ while ( i < text.length ) {
199
230
 
200
- counts = JSON.parse( data[ 'int[] faceVertexCounts' ] );
201
- indices = toTriangleIndices( indices, counts );
231
+ // Check for block comment start
232
+ if ( text[ i ] === '/' && i + 1 < text.length && text[ i + 1 ] === '*' ) {
202
233
 
203
- }
234
+ // Find the closing */
235
+ let j = i + 2;
204
236
 
205
- // position
237
+ while ( j < text.length ) {
206
238
 
207
- if ( 'point3f[] points' in data ) {
239
+ if ( text[ j ] === '*' && j + 1 < text.length && text[ j + 1 ] === '/' ) {
208
240
 
209
- const positions = JSON.parse( data[ 'point3f[] points' ].replace( /[()]*/g, '' ) );
210
- positionsLength = positions.length;
211
- let attribute = new BufferAttribute( new Float32Array( positions ), 3 );
241
+ // Found closing, skip past it
242
+ j += 2;
243
+ break;
212
244
 
213
- if ( indices !== null ) attribute = toFlatBufferAttribute( attribute, indices );
245
+ }
214
246
 
215
- geometry.setAttribute( 'position', attribute );
247
+ j ++;
216
248
 
217
- }
249
+ }
218
250
 
219
- // uv
251
+ // Move past the comment (or to end if unclosed)
252
+ i = j;
220
253
 
221
- if ( 'float2[] primvars:st' in data ) {
254
+ } else {
222
255
 
223
- data[ 'texCoord2f[] primvars:st' ] = data[ 'float2[] primvars:st' ];
256
+ result += text[ i ];
257
+ i ++;
224
258
 
225
259
  }
226
260
 
227
- if ( 'texCoord2f[] primvars:st' in data ) {
261
+ }
228
262
 
229
- uvs = JSON.parse( data[ 'texCoord2f[] primvars:st' ].replace( /[()]*/g, '' ) );
230
- let attribute = new BufferAttribute( new Float32Array( uvs ), 2 );
263
+ return result;
231
264
 
232
- if ( indices !== null ) attribute = toFlatBufferAttribute( attribute, indices );
265
+ }
233
266
 
234
- geometry.setAttribute( 'uv', attribute );
267
+ _collapseTripleQuotedStrings( text ) {
235
268
 
236
- }
269
+ let result = '';
270
+ let i = 0;
237
271
 
238
- if ( 'int[] primvars:st:indices' in data && uvs !== null ) {
272
+ while ( i < text.length ) {
239
273
 
240
- // custom uv index, overwrite uvs with new data
274
+ if ( i + 2 < text.length ) {
241
275
 
242
- const attribute = new BufferAttribute( new Float32Array( uvs ), 2 );
243
- let indices = JSON.parse( data[ 'int[] primvars:st:indices' ] );
244
- indices = toTriangleIndices( indices, counts );
245
- geometry.setAttribute( 'uv', toFlatBufferAttribute( attribute, indices ) );
276
+ const triple = text.slice( i, i + 3 );
246
277
 
247
- }
278
+ if ( triple === '\'\'\'' || triple === '"""' ) {
248
279
 
249
- // normal
280
+ const quoteChar = triple;
281
+ result += quoteChar;
282
+ i += 3;
250
283
 
251
- if ( 'normal3f[] normals' in data ) {
284
+ while ( i < text.length ) {
252
285
 
253
- const normals = JSON.parse( data[ 'normal3f[] normals' ].replace( /[()]*/g, '' ) );
254
- let attribute = new BufferAttribute( new Float32Array( normals ), 3 );
286
+ if ( i + 2 < text.length && text.slice( i, i + 3 ) === quoteChar ) {
255
287
 
256
- // normals require a special treatment in USD
288
+ result += quoteChar;
289
+ i += 3;
290
+ break;
257
291
 
258
- if ( normals.length === positionsLength ) {
292
+ } else {
259
293
 
260
- // raw normal and position data have equal length (like produced by USDZExporter)
294
+ if ( text[ i ] === '\n' ) {
261
295
 
262
- if ( indices !== null ) attribute = toFlatBufferAttribute( attribute, indices );
296
+ result += '\\n';
263
297
 
264
- } else {
298
+ } else if ( text[ i ] !== '\r' ) {
265
299
 
266
- // unequal length, normals are independent of faceVertexIndices
300
+ result += text[ i ];
267
301
 
268
- let indices = Array.from( Array( normals.length / 3 ).keys() ); // [ 0, 1, 2, 3 ... ]
269
- indices = toTriangleIndices( indices, counts );
270
- attribute = toFlatBufferAttribute( attribute, indices );
302
+ }
271
303
 
272
- }
304
+ i ++;
273
305
 
274
- geometry.setAttribute( 'normal', attribute );
306
+ }
275
307
 
276
- } else {
308
+ }
277
309
 
278
- // compute flat vertex normals
310
+ continue;
279
311
 
280
- geometry.computeVertexNormals();
312
+ }
281
313
 
282
314
  }
283
315
 
284
- return geometry;
316
+ result += text[ i ];
317
+ i ++;
285
318
 
286
319
  }
287
320
 
288
- function toTriangleIndices( rawIndices, counts ) {
289
-
290
- const indices = [];
291
-
292
- for ( let i = 0; i < counts.length; i ++ ) {
321
+ return result;
293
322
 
294
- const count = counts[ i ];
323
+ }
295
324
 
296
- const stride = i * count;
325
+ _stripInlineComment( line ) {
297
326
 
298
- if ( count === 3 ) {
327
+ // Don't strip if line starts with #usda
328
+ if ( line.trim().startsWith( '#usda' ) ) return line;
299
329
 
300
- const a = rawIndices[ stride + 0 ];
301
- const b = rawIndices[ stride + 1 ];
302
- const c = rawIndices[ stride + 2 ];
330
+ // Find # that's not inside a string
331
+ let inString = false;
332
+ let stringChar = null;
333
+ let escaped = false;
303
334
 
304
- indices.push( a, b, c );
335
+ for ( let i = 0; i < line.length; i ++ ) {
305
336
 
306
- } else if ( count === 4 ) {
337
+ const ch = line[ i ];
307
338
 
308
- const a = rawIndices[ stride + 0 ];
309
- const b = rawIndices[ stride + 1 ];
310
- const c = rawIndices[ stride + 2 ];
311
- const d = rawIndices[ stride + 3 ];
339
+ if ( escaped ) {
312
340
 
313
- indices.push( a, b, c );
314
- indices.push( a, c, d );
341
+ escaped = false;
342
+ continue;
315
343
 
316
- } else {
344
+ }
317
345
 
318
- console.warn( 'THREE.USDZLoader: Face vertex count of %s unsupported.', count );
346
+ if ( ch === '\\' ) {
319
347
 
320
- }
348
+ escaped = true;
349
+ continue;
321
350
 
322
351
  }
323
352
 
324
- return indices;
353
+ if ( ! inString && ( ch === '"' || ch === '\'' ) ) {
325
354
 
326
- }
355
+ inString = true;
356
+ stringChar = ch;
327
357
 
328
- function toFlatBufferAttribute( attribute, indices ) {
358
+ } else if ( inString && ch === stringChar ) {
329
359
 
330
- const array = attribute.array;
331
- const itemSize = attribute.itemSize;
360
+ inString = false;
361
+ stringChar = null;
332
362
 
333
- const array2 = new array.constructor( indices.length * itemSize );
363
+ } else if ( ! inString && ch === '#' ) {
334
364
 
335
- let index = 0, index2 = 0;
365
+ // Found comment start outside of string
366
+ return line.slice( 0, i ).trimEnd();
336
367
 
337
- for ( let i = 0, l = indices.length; i < l; i ++ ) {
368
+ }
338
369
 
339
- index = indices[ i ] * itemSize;
370
+ }
340
371
 
341
- for ( let j = 0; j < itemSize; j ++ ) {
372
+ return line;
342
373
 
343
- array2[ index2 ++ ] = array[ index ++ ];
374
+ }
344
375
 
345
- }
376
+ _findAssignmentOperator( line ) {
346
377
 
347
- }
378
+ // Find the first '=' that's not inside quotes
379
+ let inString = false;
380
+ let stringChar = null;
381
+ let escaped = false;
348
382
 
349
- return new BufferAttribute( array2, itemSize );
383
+ for ( let i = 0; i < line.length; i ++ ) {
350
384
 
351
- }
385
+ const ch = line[ i ];
352
386
 
353
- function findMeshMaterial( data ) {
387
+ if ( escaped ) {
354
388
 
355
- if ( ! data ) return undefined;
389
+ escaped = false;
390
+ continue;
356
391
 
357
- if ( 'rel material:binding' in data ) {
392
+ }
358
393
 
359
- const reference = data[ 'rel material:binding' ];
360
- const id = reference.replace( /^<\//, '' ).replace( />$/, '' );
361
- const parts = id.split( '/' );
394
+ if ( ch === '\\' ) {
362
395
 
363
- return findMaterial( root, ` "${ parts[ 1 ] }"` );
396
+ escaped = true;
397
+ continue;
364
398
 
365
399
  }
366
400
 
367
- return findMaterial( data );
368
-
369
- }
401
+ if ( ! inString && ( ch === '"' || ch === '\'' ) ) {
370
402
 
371
- function findMaterial( data, id = '' ) {
403
+ inString = true;
404
+ stringChar = ch;
372
405
 
373
- for ( const name in data ) {
406
+ } else if ( inString && ch === stringChar ) {
374
407
 
375
- const object = data[ name ];
408
+ inString = false;
409
+ stringChar = null;
376
410
 
377
- if ( name.startsWith( 'def Material' + id ) ) {
411
+ } else if ( ! inString && ch === '=' ) {
378
412
 
379
- return object;
413
+ return i;
380
414
 
381
- }
415
+ }
382
416
 
383
- if ( typeof object === 'object' ) {
417
+ }
384
418
 
385
- const material = findMaterial( object, id );
419
+ return - 1;
386
420
 
387
- if ( material ) return material;
421
+ }
388
422
 
389
- }
423
+ /**
424
+ * Parse USDA text and return raw spec data in specsByPath format.
425
+ * Used by USDComposer for unified scene composition.
426
+ */
427
+ parseData( text ) {
390
428
 
391
- }
429
+ const root = this.parseText( text );
430
+ const specsByPath = {};
392
431
 
393
- }
432
+ // Spec types (must match USDCParser/USDComposer)
433
+ const SpecType = {
434
+ Attribute: 1,
435
+ Prim: 6,
436
+ Relationship: 8
437
+ };
394
438
 
395
- function setTextureParams( map, data_value ) {
439
+ // Parse root metadata
440
+ const rootFields = {};
441
+ if ( '#usda 1.0' in root ) {
396
442
 
397
- // rotation, scale and translation
443
+ const header = root[ '#usda 1.0' ];
398
444
 
399
- if ( data_value[ 'float inputs:rotation' ] ) {
445
+ if ( header.upAxis ) {
400
446
 
401
- map.rotation = parseFloat( data_value[ 'float inputs:rotation' ] );
447
+ rootFields.upAxis = header.upAxis.replace( /"/g, '' );
402
448
 
403
449
  }
404
450
 
405
- if ( data_value[ 'float2 inputs:scale' ] ) {
451
+ if ( header.defaultPrim ) {
406
452
 
407
- map.repeat = new Vector2().fromArray( JSON.parse( '[' + data_value[ 'float2 inputs:scale' ].replace( /[()]*/g, '' ) + ']' ) );
453
+ rootFields.defaultPrim = header.defaultPrim.replace( /"/g, '' );
408
454
 
409
455
  }
410
456
 
411
- if ( data_value[ 'float2 inputs:translation' ] ) {
457
+ if ( header.metersPerUnit !== undefined ) {
412
458
 
413
- map.offset = new Vector2().fromArray( JSON.parse( '[' + data_value[ 'float2 inputs:translation' ].replace( /[()]*/g, '' ) + ']' ) );
459
+ rootFields.metersPerUnit = parseFloat( header.metersPerUnit );
414
460
 
415
461
  }
416
462
 
417
463
  }
418
464
 
419
- function buildMaterial( data ) {
465
+ specsByPath[ '/' ] = { specType: SpecType.Prim, fields: rootFields };
420
466
 
421
- const material = new MeshPhysicalMaterial();
467
+ // Walk the tree and build specsByPath
468
+ const walkTree = ( data, parentPath ) => {
422
469
 
423
- if ( data !== undefined ) {
470
+ const primChildren = [];
424
471
 
425
- let surface = undefined;
472
+ for ( const key in data ) {
426
473
 
427
- const surfaceConnection = data[ 'token outputs:surface.connect' ];
474
+ // Skip metadata
475
+ if ( key === '#usda 1.0' ) continue;
476
+ if ( key === 'variants' ) continue;
428
477
 
429
- if ( surfaceConnection ) {
478
+ // Check for primitive definitions
479
+ // Matches both 'def TypeName "name"' and 'def "name"' (no type)
480
+ const defMatch = key.match( DEF_MATCH_REGEX );
481
+ if ( defMatch ) {
430
482
 
431
- const match = /(\w+)\.output/.exec( surfaceConnection );
483
+ const typeName = defMatch[ 1 ] || '';
484
+ const name = defMatch[ 2 ];
485
+ const path = parentPath === '/' ? '/' + name : parentPath + '/' + name;
432
486
 
433
- if ( match ) {
487
+ primChildren.push( name );
434
488
 
435
- const surfaceName = match[ 1 ];
436
- surface = data[ `def Shader "${surfaceName}"` ];
489
+ const primFields = { typeName };
490
+ const primData = data[ key ];
437
491
 
438
- }
492
+ // Extract attributes and relationships from this prim
493
+ this._extractPrimData( primData, path, primFields, specsByPath, SpecType );
439
494
 
440
- }
495
+ specsByPath[ path ] = { specType: SpecType.Prim, fields: primFields };
441
496
 
442
- if ( surface !== undefined ) {
497
+ // Recurse into children
498
+ walkTree( primData, path );
443
499
 
444
- if ( 'color3f inputs:diffuseColor.connect' in surface ) {
500
+ }
445
501
 
446
- const path = surface[ 'color3f inputs:diffuseColor.connect' ];
447
- const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
502
+ }
448
503
 
449
- material.map = buildTexture( sampler );
450
- material.map.colorSpace = SRGBColorSpace;
504
+ // Add primChildren to parent spec
505
+ if ( primChildren.length > 0 && specsByPath[ parentPath ] ) {
451
506
 
452
- if ( 'def Shader "Transform2d_diffuse"' in data ) {
507
+ specsByPath[ parentPath ].fields.primChildren = primChildren;
453
508
 
454
- setTextureParams( material.map, data[ 'def Shader "Transform2d_diffuse"' ] );
509
+ }
455
510
 
456
- }
511
+ };
457
512
 
458
- } else if ( 'color3f inputs:diffuseColor' in surface ) {
513
+ walkTree( root, '/' );
459
514
 
460
- const color = surface[ 'color3f inputs:diffuseColor' ].replace( /[()]*/g, '' );
461
- material.color.fromArray( JSON.parse( '[' + color + ']' ) );
515
+ return { specsByPath };
462
516
 
463
- }
517
+ }
464
518
 
465
- if ( 'color3f inputs:emissiveColor.connect' in surface ) {
519
+ _extractPrimData( data, path, primFields, specsByPath, SpecType ) {
466
520
 
467
- const path = surface[ 'color3f inputs:emissiveColor.connect' ];
468
- const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
521
+ if ( ! data || typeof data !== 'object' ) return;
469
522
 
470
- material.emissiveMap = buildTexture( sampler );
471
- material.emissiveMap.colorSpace = SRGBColorSpace;
472
- material.emissive.set( 0xffffff );
523
+ for ( const key in data ) {
473
524
 
474
- if ( 'def Shader "Transform2d_emissive"' in data ) {
525
+ // Skip nested defs (handled by walkTree)
526
+ if ( key.startsWith( 'def ' ) ) continue;
475
527
 
476
- setTextureParams( material.emissiveMap, data[ 'def Shader "Transform2d_emissive"' ] );
528
+ if ( key === 'prepend references' ) {
477
529
 
478
- }
530
+ primFields.references = [ data[ key ] ];
531
+ continue;
479
532
 
480
- } else if ( 'color3f inputs:emissiveColor' in surface ) {
533
+ }
481
534
 
482
- const color = surface[ 'color3f inputs:emissiveColor' ].replace( /[()]*/g, '' );
483
- material.emissive.fromArray( JSON.parse( '[' + color + ']' ) );
535
+ if ( key === 'payload' ) {
484
536
 
485
- }
537
+ primFields.payload = data[ key ];
538
+ continue;
486
539
 
487
- if ( 'normal3f inputs:normal.connect' in surface ) {
540
+ }
488
541
 
489
- const path = surface[ 'normal3f inputs:normal.connect' ];
490
- const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
542
+ if ( key === 'variants' ) {
491
543
 
492
- material.normalMap = buildTexture( sampler );
493
- material.normalMap.colorSpace = NoColorSpace;
544
+ const variantSelection = {};
545
+ const variants = data[ key ];
494
546
 
495
- if ( 'def Shader "Transform2d_normal"' in data ) {
547
+ for ( const vKey in variants ) {
496
548
 
497
- setTextureParams( material.normalMap, data[ 'def Shader "Transform2d_normal"' ] );
549
+ const match = vKey.match( VARIANT_STRING_REGEX );
550
+ if ( match ) {
498
551
 
499
- }
552
+ const variantSetName = match[ 1 ];
553
+ const variantValue = variants[ vKey ].replace( /"/g, '' );
554
+ variantSelection[ variantSetName ] = variantValue;
500
555
 
501
556
  }
502
557
 
503
- if ( 'float inputs:roughness.connect' in surface ) {
504
-
505
- const path = surface[ 'float inputs:roughness.connect' ];
506
- const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
507
-
508
- material.roughness = 1.0;
509
- material.roughnessMap = buildTexture( sampler );
510
- material.roughnessMap.colorSpace = NoColorSpace;
511
-
512
- if ( 'def Shader "Transform2d_roughness"' in data ) {
513
-
514
- setTextureParams( material.roughnessMap, data[ 'def Shader "Transform2d_roughness"' ] );
515
-
516
- }
517
-
518
- } else if ( 'float inputs:roughness' in surface ) {
558
+ }
519
559
 
520
- material.roughness = parseFloat( surface[ 'float inputs:roughness' ] );
560
+ if ( Object.keys( variantSelection ).length > 0 ) {
521
561
 
522
- }
562
+ primFields.variantSelection = variantSelection;
523
563
 
524
- if ( 'float inputs:metallic.connect' in surface ) {
525
-
526
- const path = surface[ 'float inputs:metallic.connect' ];
527
- const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
564
+ }
528
565
 
529
- material.metalness = 1.0;
530
- material.metalnessMap = buildTexture( sampler );
531
- material.metalnessMap.colorSpace = NoColorSpace;
566
+ continue;
532
567
 
533
- if ( 'def Shader "Transform2d_metallic"' in data ) {
568
+ }
534
569
 
535
- setTextureParams( material.metalnessMap, data[ 'def Shader "Transform2d_metallic"' ] );
570
+ if ( key.startsWith( 'rel ' ) ) {
536
571
 
537
- }
572
+ const relName = key.slice( 4 );
573
+ const relPath = path + '.' + relName;
574
+ const target = data[ key ].replace( /[<>]/g, '' );
575
+ specsByPath[ relPath ] = {
576
+ specType: SpecType.Relationship,
577
+ fields: { targetPaths: [ target ] }
578
+ };
579
+ continue;
538
580
 
539
- } else if ( 'float inputs:metallic' in surface ) {
581
+ }
540
582
 
541
- material.metalness = parseFloat( surface[ 'float inputs:metallic' ] );
583
+ // Handle xformOpOrder
584
+ if ( key.includes( 'xformOpOrder' ) ) {
542
585
 
543
- }
586
+ const ops = data[ key ]
587
+ .replace( /[\[\]]/g, '' )
588
+ .split( ',' )
589
+ .map( s => s.trim().replace( /"/g, '' ) );
590
+ primFields.xformOpOrder = ops;
591
+ continue;
544
592
 
545
- if ( 'float inputs:clearcoat.connect' in surface ) {
593
+ }
546
594
 
547
- const path = surface[ 'float inputs:clearcoat.connect' ];
548
- const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
595
+ // Handle typed attributes
596
+ // Format: [qualifier] type attrName (e.g., "uniform token[] joints", "float3 position")
597
+ const attrMatch = key.match( ATTR_MATCH_REGEX );
598
+ if ( attrMatch ) {
549
599
 
550
- material.clearcoat = 1.0;
551
- material.clearcoatMap = buildTexture( sampler );
552
- material.clearcoatMap.colorSpace = NoColorSpace;
600
+ const valueType = attrMatch[ 1 ];
601
+ const attrName = attrMatch[ 2 ];
602
+ const rawValue = data[ key ];
553
603
 
554
- if ( 'def Shader "Transform2d_clearcoat"' in data ) {
604
+ // Handle connection attributes (e.g., "inputs:normal.connect = </path>")
605
+ if ( attrName.endsWith( '.connect' ) ) {
555
606
 
556
- setTextureParams( material.clearcoatMap, data[ 'def Shader "Transform2d_clearcoat"' ] );
607
+ const baseAttrName = attrName.slice( 0, - 8 ); // Remove '.connect'
608
+ const attrPath = path + '.' + baseAttrName;
557
609
 
558
- }
610
+ // Parse connection path - extract from <path> format
611
+ let connPath = String( rawValue ).trim();
612
+ if ( connPath.startsWith( '<' ) ) connPath = connPath.slice( 1 );
613
+ if ( connPath.endsWith( '>' ) ) connPath = connPath.slice( 0, - 1 );
559
614
 
560
- } else if ( 'float inputs:clearcoat' in surface ) {
615
+ // Get or create the attribute spec
616
+ if ( ! specsByPath[ attrPath ] ) {
561
617
 
562
- material.clearcoat = parseFloat( surface[ 'float inputs:clearcoat' ] );
618
+ specsByPath[ attrPath ] = {
619
+ specType: SpecType.Attribute,
620
+ fields: { typeName: valueType }
621
+ };
563
622
 
564
623
  }
565
624
 
566
- if ( 'float inputs:clearcoatRoughness.connect' in surface ) {
625
+ specsByPath[ attrPath ].fields.connectionPaths = [ connPath ];
626
+ continue;
567
627
 
568
- const path = surface[ 'float inputs:clearcoatRoughness.connect' ];
569
- const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
628
+ }
570
629
 
571
- material.clearcoatRoughness = 1.0;
572
- material.clearcoatRoughnessMap = buildTexture( sampler );
573
- material.clearcoatRoughnessMap.colorSpace = NoColorSpace;
630
+ // Handle timeSamples attributes specially
631
+ if ( attrName.endsWith( '.timeSamples' ) && typeof rawValue === 'object' ) {
574
632
 
575
- if ( 'def Shader "Transform2d_clearcoatRoughness"' in data ) {
633
+ const baseAttrName = attrName.slice( 0, - 12 ); // Remove '.timeSamples'
634
+ const attrPath = path + '.' + baseAttrName;
576
635
 
577
- setTextureParams( material.clearcoatRoughnessMap, data[ 'def Shader "Transform2d_clearcoatRoughness"' ] );
636
+ // Parse timeSamples dictionary into times and values arrays
637
+ const times = [];
638
+ const values = [];
578
639
 
579
- }
640
+ for ( const frameKey in rawValue ) {
580
641
 
581
- } else if ( 'float inputs:clearcoatRoughness' in surface ) {
642
+ const frame = parseFloat( frameKey );
643
+ if ( isNaN( frame ) ) continue;
582
644
 
583
- material.clearcoatRoughness = parseFloat( surface[ 'float inputs:clearcoatRoughness' ] );
645
+ times.push( frame );
646
+ values.push( this._parseAttributeValue( valueType, rawValue[ frameKey ] ) );
584
647
 
585
648
  }
586
649
 
587
- if ( 'float inputs:ior' in surface ) {
650
+ // Sort by time
651
+ const sorted = times.map( ( t, i ) => ( { t, v: values[ i ] } ) ).sort( ( a, b ) => a.t - b.t );
588
652
 
589
- material.ior = parseFloat( surface[ 'float inputs:ior' ] );
590
-
591
- }
592
-
593
- if ( 'float inputs:occlusion.connect' in surface ) {
594
-
595
- const path = surface[ 'float inputs:occlusion.connect' ];
596
- const sampler = findTexture( root, /(\w+).output/.exec( path )[ 1 ] );
597
-
598
- material.aoMap = buildTexture( sampler );
599
- material.aoMap.colorSpace = NoColorSpace;
600
-
601
- if ( 'def Shader "Transform2d_occlusion"' in data ) {
653
+ specsByPath[ attrPath ] = {
654
+ specType: SpecType.Attribute,
655
+ fields: {
656
+ timeSamples: { times: sorted.map( s => s.t ), values: sorted.map( s => s.v ) },
657
+ typeName: valueType
658
+ }
659
+ };
602
660
 
603
- setTextureParams( material.aoMap, data[ 'def Shader "Transform2d_occlusion"' ] );
661
+ } else {
604
662
 
605
- }
663
+ // Parse value based on type
664
+ const parsedValue = this._parseAttributeValue( valueType, rawValue );
606
665
 
607
- }
666
+ // Store as attribute spec
667
+ const attrPath = path + '.' + attrName;
668
+ specsByPath[ attrPath ] = {
669
+ specType: SpecType.Attribute,
670
+ fields: { default: parsedValue, typeName: valueType }
671
+ };
608
672
 
609
673
  }
610
674
 
611
675
  }
612
676
 
613
- return material;
614
-
615
677
  }
616
678
 
617
- function findTexture( data, id ) {
679
+ }
618
680
 
619
- for ( const name in data ) {
681
+ _parseAttributeValue( valueType, rawValue ) {
620
682
 
621
- const object = data[ name ];
683
+ if ( rawValue === undefined || rawValue === null ) return undefined;
622
684
 
623
- if ( name.startsWith( `def Shader "${ id }"` ) ) {
685
+ const str = String( rawValue ).trim();
624
686
 
625
- return object;
687
+ // Array types
688
+ if ( valueType.endsWith( '[]' ) ) {
626
689
 
627
- }
690
+ // Parse JSON-like arrays
691
+ try {
628
692
 
629
- if ( typeof object === 'object' ) {
693
+ // Handle arrays with parentheses like [(1,2,3), (4,5,6)]
694
+ // Remove trailing comma (valid in USDA but not JSON)
695
+ let cleaned = str.replace( /\(/g, '[' ).replace( /\)/g, ']' );
696
+ if ( cleaned.endsWith( ',' ) ) cleaned = cleaned.slice( 0, - 1 );
697
+ const parsed = JSON.parse( cleaned );
630
698
 
631
- const texture = findTexture( object, id );
699
+ // Flatten nested arrays for types like point3f[]
700
+ if ( Array.isArray( parsed ) && Array.isArray( parsed[ 0 ] ) ) {
632
701
 
633
- if ( texture ) return texture;
702
+ return parsed.flat();
634
703
 
635
704
  }
636
705
 
637
- }
638
-
639
- }
706
+ return parsed;
640
707
 
641
- function buildTexture( data ) {
708
+ } catch ( e ) {
642
709
 
643
- if ( 'asset inputs:file' in data ) {
710
+ // Try simple array parsing
711
+ const cleaned = str.replace( /[\[\]]/g, '' );
712
+ return cleaned.split( ',' ).map( s => {
644
713
 
645
- const path = data[ 'asset inputs:file' ].replace( /@*/g, '' ).trim();
714
+ const trimmed = s.trim();
715
+ const num = parseFloat( trimmed );
716
+ return isNaN( num ) ? trimmed.replace( /"/g, '' ) : num;
646
717
 
647
- const loader = new TextureLoader();
718
+ } );
648
719
 
649
- const texture = loader.load( assets[ path ] );
650
-
651
- const map = {
652
- '"clamp"': ClampToEdgeWrapping,
653
- '"mirror"': MirroredRepeatWrapping,
654
- '"repeat"': RepeatWrapping
655
- };
720
+ }
656
721
 
657
- if ( 'token inputs:wrapS' in data ) {
722
+ }
658
723
 
659
- texture.wrapS = map[ data[ 'token inputs:wrapS' ] ];
724
+ // Vector types (double3, float3, point3f, etc.)
725
+ if ( valueType.includes( '3' ) || valueType.includes( '2' ) || valueType.includes( '4' ) ) {
660
726
 
661
- }
727
+ // Parse (x, y, z) format
728
+ const cleaned = str.replace( /[()]/g, '' );
729
+ const values = cleaned.split( ',' ).map( s => parseFloat( s.trim() ) );
730
+ return values;
662
731
 
663
- if ( 'token inputs:wrapT' in data ) {
732
+ }
664
733
 
665
- texture.wrapT = map[ data[ 'token inputs:wrapT' ] ];
734
+ // Quaternion types (quatf, quatd, quath)
735
+ // Text format is (w, x, y, z), convert to (x, y, z, w)
736
+ if ( valueType.startsWith( 'quat' ) ) {
666
737
 
667
- }
738
+ const cleaned = str.replace( /[()]/g, '' );
739
+ const values = cleaned.split( ',' ).map( s => parseFloat( s.trim() ) );
740
+ return [ values[ 1 ], values[ 2 ], values[ 3 ], values[ 0 ] ];
668
741
 
669
- return texture;
742
+ }
670
743
 
671
- }
744
+ // Matrix types
745
+ if ( valueType.includes( 'matrix' ) ) {
672
746
 
673
- return null;
747
+ const cleaned = str.replace( /[()]/g, '' );
748
+ const values = cleaned.split( ',' ).map( s => parseFloat( s.trim() ) );
749
+ return values;
674
750
 
675
751
  }
676
752
 
677
- function buildObject( data ) {
753
+ // Scalar numeric types
754
+ if ( valueType === 'float' || valueType === 'double' || valueType === 'int' ) {
678
755
 
679
- const geometry = buildGeometry( findMeshGeometry( data ) );
680
- const material = buildMaterial( findMeshMaterial( data ) );
756
+ return parseFloat( str );
681
757
 
682
- const mesh = geometry ? new Mesh( geometry, material ) : new Object3D();
758
+ }
683
759
 
684
- if ( 'matrix4d xformOp:transform' in data ) {
760
+ // String/token types
761
+ if ( valueType === 'string' || valueType === 'token' ) {
685
762
 
686
- const array = JSON.parse( '[' + data[ 'matrix4d xformOp:transform' ].replace( /[()]*/g, '' ) + ']' );
763
+ return this._parseString( str );
687
764
 
688
- mesh.matrix.fromArray( array );
689
- mesh.matrix.decompose( mesh.position, mesh.quaternion, mesh.scale );
765
+ }
690
766
 
691
- }
767
+ // Asset path
768
+ if ( valueType === 'asset' ) {
692
769
 
693
- return mesh;
770
+ return str.replace( /@/g, '' ).replace( /"/g, '' );
694
771
 
695
772
  }
696
773
 
697
- function buildHierarchy( data, group ) {
698
-
699
- for ( const name in data ) {
774
+ // Default: return as string with quotes removed
775
+ return this._parseString( str );
700
776
 
701
- if ( name.startsWith( 'def Scope' ) ) {
777
+ }
702
778
 
703
- buildHierarchy( data[ name ], group );
779
+ _parseString( str ) {
704
780
 
705
- } else if ( name.startsWith( 'def Xform' ) ) {
781
+ // Remove surrounding quotes
782
+ if ( ( str.startsWith( '"' ) && str.endsWith( '"' ) ) ||
783
+ ( str.startsWith( '\'' ) && str.endsWith( '\'' ) ) ) {
706
784
 
707
- const mesh = buildObject( data[ name ] );
785
+ str = str.slice( 1, - 1 );
708
786
 
709
- if ( /def Xform "(\w+)"/.test( name ) ) {
787
+ }
710
788
 
711
- mesh.name = /def Xform "(\w+)"/.exec( name )[ 1 ];
789
+ // Handle escape sequences
790
+ let result = '';
791
+ let i = 0;
712
792
 
713
- }
793
+ while ( i < str.length ) {
714
794
 
715
- group.add( mesh );
795
+ if ( str[ i ] === '\\' && i + 1 < str.length ) {
716
796
 
717
- buildHierarchy( data[ name ], mesh );
797
+ const next = str[ i + 1 ];
718
798
 
719
- }
799
+ switch ( next ) {
720
800
 
721
- }
801
+ case 'n': result += '\n'; break;
802
+ case 't': result += '\t'; break;
803
+ case 'r': result += '\r'; break;
804
+ case '\\': result += '\\'; break;
805
+ case '"': result += '"'; break;
806
+ case '\'': result += '\''; break;
807
+ default: result += next; break;
722
808
 
723
- }
809
+ }
724
810
 
725
- function buildGroup( data ) {
811
+ i += 2;
726
812
 
727
- const group = new Group();
813
+ } else {
728
814
 
729
- buildHierarchy( data, group );
815
+ result += str[ i ];
816
+ i ++;
730
817
 
731
- return group;
818
+ }
732
819
 
733
820
  }
734
821
 
735
- return buildGroup( root );
822
+ return result;
736
823
 
737
824
  }
738
825