@plastic-software/three 0.175.14 → 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.
Files changed (572) hide show
  1. package/README.md +4 -4
  2. package/build/three.cjs +8402 -6787
  3. package/build/three.core.js +8007 -6688
  4. package/build/three.core.min.js +1 -1
  5. package/build/three.module.js +397 -102
  6. package/build/three.module.min.js +1 -1
  7. package/build/three.tsl.js +84 -27
  8. package/build/three.tsl.min.js +1 -1
  9. package/build/three.webgpu.js +6831 -2838
  10. package/build/three.webgpu.min.js +1 -1
  11. package/build/three.webgpu.nodes.js +6648 -2838
  12. package/build/three.webgpu.nodes.min.js +1 -1
  13. package/examples/jsm/Addons.js +1 -3
  14. package/examples/jsm/animation/AnimationClipCreator.js +1 -0
  15. package/examples/jsm/animation/CCDIKSolver.js +6 -3
  16. package/examples/jsm/capabilities/WebGL.js +1 -27
  17. package/examples/jsm/capabilities/WebGPU.js +2 -1
  18. package/examples/jsm/controls/ArcballControls.js +15 -4
  19. package/examples/jsm/controls/DragControls.js +1 -0
  20. package/examples/jsm/controls/FirstPersonControls.js +1 -0
  21. package/examples/jsm/controls/FlyControls.js +1 -0
  22. package/examples/jsm/controls/MapControls.js +1 -0
  23. package/examples/jsm/controls/OrbitControls.js +1 -0
  24. package/examples/jsm/controls/PointerLockControls.js +5 -3
  25. package/examples/jsm/controls/TrackballControls.js +1 -0
  26. package/examples/jsm/controls/TransformControls.js +62 -14
  27. package/examples/jsm/csm/CSM.js +2 -0
  28. package/examples/jsm/csm/CSMFrustum.js +2 -0
  29. package/examples/jsm/csm/CSMHelper.js +1 -0
  30. package/examples/jsm/csm/CSMShader.js +4 -1
  31. package/examples/jsm/csm/CSMShadowNode.js +22 -8
  32. package/examples/jsm/curves/CurveExtras.js +14 -0
  33. package/examples/jsm/curves/NURBSCurve.js +1 -0
  34. package/examples/jsm/curves/NURBSSurface.js +2 -0
  35. package/examples/jsm/curves/NURBSUtils.js +4 -1
  36. package/examples/jsm/curves/NURBSVolume.js +2 -0
  37. package/examples/jsm/effects/AnaglyphEffect.js +2 -0
  38. package/examples/jsm/effects/AsciiEffect.js +2 -0
  39. package/examples/jsm/effects/OutlineEffect.js +2 -0
  40. package/examples/jsm/effects/ParallaxBarrierEffect.js +2 -0
  41. package/examples/jsm/effects/StereoEffect.js +2 -0
  42. package/examples/jsm/environments/DebugEnvironment.js +1 -0
  43. package/examples/jsm/environments/RoomEnvironment.js +57 -38
  44. package/examples/jsm/exporters/DRACOExporter.js +4 -2
  45. package/examples/jsm/exporters/EXRExporter.js +2 -0
  46. package/examples/jsm/exporters/GLTFExporter.js +7 -4
  47. package/examples/jsm/exporters/KTX2Exporter.js +2 -0
  48. package/examples/jsm/exporters/OBJExporter.js +3 -1
  49. package/examples/jsm/exporters/PLYExporter.js +4 -2
  50. package/examples/jsm/exporters/STLExporter.js +2 -0
  51. package/examples/jsm/exporters/USDZExporter.js +679 -300
  52. package/examples/jsm/geometries/BoxLineGeometry.js +1 -0
  53. package/examples/jsm/geometries/ConvexGeometry.js +1 -0
  54. package/examples/jsm/geometries/DecalGeometry.js +1 -0
  55. package/examples/jsm/geometries/ParametricFunctions.js +4 -1
  56. package/examples/jsm/geometries/ParametricGeometry.js +1 -0
  57. package/examples/jsm/geometries/RoundedBoxGeometry.js +48 -8
  58. package/examples/jsm/geometries/TeapotGeometry.js +1 -0
  59. package/examples/jsm/geometries/TextGeometry.js +1 -0
  60. package/examples/jsm/helpers/LightProbeHelper.js +1 -0
  61. package/examples/jsm/helpers/LightProbeHelperGPU.js +1 -0
  62. package/examples/jsm/helpers/OctreeHelper.js +1 -0
  63. package/examples/jsm/helpers/PositionalAudioHelper.js +1 -0
  64. package/examples/jsm/helpers/RapierHelper.js +59 -0
  65. package/examples/jsm/helpers/RectAreaLightHelper.js +1 -0
  66. package/examples/jsm/helpers/TextureHelper.js +1 -0
  67. package/examples/jsm/helpers/TextureHelperGPU.js +5 -4
  68. package/examples/jsm/helpers/VertexNormalsHelper.js +1 -0
  69. package/examples/jsm/helpers/VertexTangentsHelper.js +1 -0
  70. package/examples/jsm/helpers/ViewHelper.js +1 -0
  71. package/examples/jsm/interactive/HTMLMesh.js +11 -2
  72. package/examples/jsm/interactive/InteractiveGroup.js +1 -0
  73. package/examples/jsm/interactive/SelectionBox.js +2 -0
  74. package/examples/jsm/interactive/SelectionHelper.js +2 -0
  75. package/examples/jsm/libs/meshopt_decoder.module.js +75 -58
  76. package/examples/jsm/lighting/TiledLighting.js +1 -0
  77. package/examples/jsm/lights/LightProbeGenerator.js +15 -3
  78. package/examples/jsm/lights/RectAreaLightTexturesLib.js +1 -0
  79. package/examples/jsm/lights/RectAreaLightUniformsLib.js +1 -0
  80. package/examples/jsm/lines/Line2.js +1 -0
  81. package/examples/jsm/lines/LineGeometry.js +1 -0
  82. package/examples/jsm/lines/LineMaterial.js +4 -4
  83. package/examples/jsm/lines/LineSegments2.js +1 -0
  84. package/examples/jsm/lines/LineSegmentsGeometry.js +1 -0
  85. package/examples/jsm/lines/Wireframe.js +1 -0
  86. package/examples/jsm/lines/WireframeGeometry2.js +1 -0
  87. package/examples/jsm/lines/webgpu/Line2.js +1 -0
  88. package/examples/jsm/lines/webgpu/LineSegments2.js +3 -1
  89. package/examples/jsm/lines/webgpu/Wireframe.js +1 -0
  90. package/examples/jsm/loaders/3DMLoader.js +1 -0
  91. package/examples/jsm/loaders/3MFLoader.js +1 -0
  92. package/examples/jsm/loaders/AMFLoader.js +1 -0
  93. package/examples/jsm/loaders/BVHLoader.js +1 -0
  94. package/examples/jsm/loaders/ColladaLoader.js +6 -5
  95. package/examples/jsm/loaders/DDSLoader.js +1 -0
  96. package/examples/jsm/loaders/DRACOLoader.js +2 -1
  97. package/examples/jsm/loaders/EXRLoader.js +211 -22
  98. package/examples/jsm/loaders/FBXLoader.js +25 -23
  99. package/examples/jsm/loaders/FontLoader.js +1 -0
  100. package/examples/jsm/loaders/GCodeLoader.js +1 -0
  101. package/examples/jsm/loaders/GLTFLoader.js +10 -82
  102. package/examples/jsm/loaders/HDRCubeTextureLoader.js +1 -0
  103. package/examples/jsm/loaders/IESLoader.js +1 -0
  104. package/examples/jsm/loaders/KMZLoader.js +1 -0
  105. package/examples/jsm/loaders/KTX2Loader.js +67 -26
  106. package/examples/jsm/loaders/KTXLoader.js +1 -0
  107. package/examples/jsm/loaders/LDrawLoader.js +55 -3
  108. package/examples/jsm/loaders/LUT3dlLoader.js +1 -0
  109. package/examples/jsm/loaders/LUTCubeLoader.js +1 -0
  110. package/examples/jsm/loaders/LUTImageLoader.js +1 -0
  111. package/examples/jsm/loaders/LWOLoader.js +1 -13
  112. package/examples/jsm/loaders/LottieLoader.js +15 -0
  113. package/examples/jsm/loaders/MD2Loader.js +1 -0
  114. package/examples/jsm/loaders/MDDLoader.js +1 -0
  115. package/examples/jsm/loaders/MTLLoader.js +4 -3
  116. package/examples/jsm/loaders/MaterialXLoader.js +213 -30
  117. package/examples/jsm/loaders/NRRDLoader.js +1 -0
  118. package/examples/jsm/loaders/OBJLoader.js +1 -0
  119. package/examples/jsm/loaders/PCDLoader.js +122 -19
  120. package/examples/jsm/loaders/PDBLoader.js +1 -0
  121. package/examples/jsm/loaders/PLYLoader.js +1 -0
  122. package/examples/jsm/loaders/PVRLoader.js +1 -0
  123. package/examples/jsm/loaders/RGBELoader.js +1 -0
  124. package/examples/jsm/loaders/RGBMLoader.js +1 -0
  125. package/examples/jsm/loaders/STLLoader.js +1 -0
  126. package/examples/jsm/loaders/SVGLoader.js +1 -0
  127. package/examples/jsm/loaders/TDSLoader.js +1 -0
  128. package/examples/jsm/loaders/TGALoader.js +1 -0
  129. package/examples/jsm/loaders/TIFFLoader.js +1 -0
  130. package/examples/jsm/loaders/TTFLoader.js +14 -1
  131. package/examples/jsm/loaders/USDLoader.js +219 -0
  132. package/examples/jsm/loaders/USDZLoader.js +4 -891
  133. package/examples/jsm/loaders/UltraHDRLoader.js +1 -0
  134. package/examples/jsm/loaders/VOXLoader.js +1 -0
  135. package/examples/jsm/loaders/VRMLLoader.js +3 -2
  136. package/examples/jsm/loaders/VTKLoader.js +1 -0
  137. package/examples/jsm/loaders/XYZLoader.js +1 -0
  138. package/examples/jsm/loaders/lwo/IFFParser.js +74 -74
  139. package/examples/jsm/loaders/usd/USDAParser.js +741 -0
  140. package/examples/jsm/loaders/usd/USDCParser.js +17 -0
  141. package/examples/jsm/materials/LDrawConditionalLineMaterial.js +1 -0
  142. package/examples/jsm/materials/LDrawConditionalLineNodeMaterial.js +1 -0
  143. package/examples/jsm/materials/MeshPostProcessingMaterial.js +1 -0
  144. package/examples/jsm/math/Capsule.js +2 -0
  145. package/examples/jsm/math/ColorConverter.js +1 -0
  146. package/examples/jsm/math/ConvexHull.js +2 -0
  147. package/examples/jsm/math/ImprovedNoise.js +19 -14
  148. package/examples/jsm/math/Lut.js +2 -0
  149. package/examples/jsm/math/MeshSurfaceSampler.js +2 -0
  150. package/examples/jsm/math/OBB.js +2 -0
  151. package/examples/jsm/math/Octree.js +20 -1
  152. package/examples/jsm/math/SimplexNoise.js +2 -0
  153. package/examples/jsm/misc/ConvexObjectBreaker.js +3 -1
  154. package/examples/jsm/misc/GPUComputationRenderer.js +2 -0
  155. package/examples/jsm/misc/Gyroscope.js +1 -0
  156. package/examples/jsm/misc/MD2Character.js +2 -0
  157. package/examples/jsm/misc/MD2CharacterComplex.js +5 -3
  158. package/examples/jsm/misc/MorphAnimMesh.js +1 -0
  159. package/examples/jsm/misc/MorphBlendMesh.js +1 -0
  160. package/examples/jsm/misc/ProgressiveLightMap.js +2 -0
  161. package/examples/jsm/misc/ProgressiveLightMapGPU.js +2 -0
  162. package/examples/jsm/misc/RollerCoaster.js +5 -0
  163. package/examples/jsm/misc/TubePainter.js +1 -0
  164. package/examples/jsm/misc/Volume.js +2 -0
  165. package/examples/jsm/misc/VolumeSlice.js +1 -0
  166. package/examples/jsm/modifiers/CurveModifier.js +3 -0
  167. package/examples/jsm/modifiers/CurveModifierGPU.js +2 -0
  168. package/examples/jsm/modifiers/EdgeSplitModifier.js +2 -0
  169. package/examples/jsm/modifiers/SimplifyModifier.js +2 -0
  170. package/examples/jsm/modifiers/TessellateModifier.js +2 -0
  171. package/examples/jsm/objects/GroundedSkybox.js +1 -0
  172. package/examples/jsm/objects/Lensflare.js +3 -0
  173. package/examples/jsm/objects/LensflareMesh.js +4 -3
  174. package/examples/jsm/objects/MarchingCubes.js +2 -0
  175. package/examples/jsm/objects/Reflector.js +1 -0
  176. package/examples/jsm/objects/ReflectorForSSRPass.js +1 -0
  177. package/examples/jsm/objects/Refractor.js +1 -0
  178. package/examples/jsm/objects/ShadowMesh.js +1 -0
  179. package/examples/jsm/objects/Sky.js +2 -1
  180. package/examples/jsm/objects/SkyMesh.js +22 -19
  181. package/examples/jsm/objects/Water.js +1 -0
  182. package/examples/jsm/objects/Water2.js +1 -0
  183. package/examples/jsm/objects/Water2Mesh.js +3 -1
  184. package/examples/jsm/objects/WaterMesh.js +2 -1
  185. package/examples/jsm/physics/AmmoPhysics.js +1 -0
  186. package/examples/jsm/physics/JoltPhysics.js +1 -0
  187. package/examples/jsm/physics/RapierPhysics.js +149 -13
  188. package/examples/jsm/postprocessing/AfterimagePass.js +20 -2
  189. package/examples/jsm/postprocessing/BloomPass.js +2 -1
  190. package/examples/jsm/postprocessing/BokehPass.js +2 -1
  191. package/examples/jsm/postprocessing/ClearPass.js +1 -0
  192. package/examples/jsm/postprocessing/CubeTexturePass.js +1 -0
  193. package/examples/jsm/postprocessing/DotScreenPass.js +1 -0
  194. package/examples/jsm/postprocessing/EffectComposer.js +4 -2
  195. package/examples/jsm/postprocessing/FXAAPass.js +40 -0
  196. package/examples/jsm/postprocessing/FilmPass.js +1 -0
  197. package/examples/jsm/postprocessing/GTAOPass.js +14 -12
  198. package/examples/jsm/postprocessing/GlitchPass.js +2 -1
  199. package/examples/jsm/postprocessing/HalftonePass.js +2 -1
  200. package/examples/jsm/postprocessing/LUTPass.js +1 -0
  201. package/examples/jsm/postprocessing/MaskPass.js +1 -0
  202. package/examples/jsm/postprocessing/OutlinePass.js +22 -19
  203. package/examples/jsm/postprocessing/OutputPass.js +1 -0
  204. package/examples/jsm/postprocessing/Pass.js +3 -1
  205. package/examples/jsm/postprocessing/RenderPass.js +1 -0
  206. package/examples/jsm/postprocessing/RenderPixelatedPass.js +2 -1
  207. package/examples/jsm/postprocessing/RenderTransitionPass.js +4 -3
  208. package/examples/jsm/postprocessing/SAOPass.js +3 -2
  209. package/examples/jsm/postprocessing/SMAAPass.js +3 -2
  210. package/examples/jsm/postprocessing/SSAARenderPass.js +2 -1
  211. package/examples/jsm/postprocessing/SSAOPass.js +12 -10
  212. package/examples/jsm/postprocessing/SSRPass.js +4 -3
  213. package/examples/jsm/postprocessing/SavePass.js +2 -1
  214. package/examples/jsm/postprocessing/ShaderPass.js +1 -0
  215. package/examples/jsm/postprocessing/TAARenderPass.js +1 -0
  216. package/examples/jsm/postprocessing/TexturePass.js +1 -0
  217. package/examples/jsm/postprocessing/UnrealBloomPass.js +2 -1
  218. package/examples/jsm/renderers/CSS2DRenderer.js +3 -0
  219. package/examples/jsm/renderers/CSS3DRenderer.js +4 -0
  220. package/examples/jsm/renderers/Projector.js +2 -0
  221. package/examples/jsm/renderers/SVGRenderer.js +3 -0
  222. package/examples/jsm/shaders/ACESFilmicToneMappingShader.js +4 -1
  223. package/examples/jsm/shaders/AfterimageShader.js +4 -1
  224. package/examples/jsm/shaders/BasicShader.js +4 -1
  225. package/examples/jsm/shaders/BleachBypassShader.js +4 -1
  226. package/examples/jsm/shaders/BlendShader.js +4 -1
  227. package/examples/jsm/shaders/BokehShader.js +4 -1
  228. package/examples/jsm/shaders/BokehShader2.js +4 -1
  229. package/examples/jsm/shaders/BrightnessContrastShader.js +4 -1
  230. package/examples/jsm/shaders/ColorCorrectionShader.js +4 -1
  231. package/examples/jsm/shaders/ColorifyShader.js +4 -1
  232. package/examples/jsm/shaders/ConvolutionShader.js +4 -1
  233. package/examples/jsm/shaders/CopyShader.js +4 -1
  234. package/examples/jsm/shaders/DOFMipMapShader.js +4 -1
  235. package/examples/jsm/shaders/DepthLimitedBlurShader.js +4 -1
  236. package/examples/jsm/shaders/DigitalGlitch.js +4 -1
  237. package/examples/jsm/shaders/DotScreenShader.js +4 -1
  238. package/examples/jsm/shaders/ExposureShader.js +4 -1
  239. package/examples/jsm/shaders/FXAAShader.js +4 -1
  240. package/examples/jsm/shaders/FilmShader.js +4 -1
  241. package/examples/jsm/shaders/FocusShader.js +4 -1
  242. package/examples/jsm/shaders/FreiChenShader.js +4 -1
  243. package/examples/jsm/shaders/GTAOShader.js +4 -1
  244. package/examples/jsm/shaders/GammaCorrectionShader.js +4 -1
  245. package/examples/jsm/shaders/GodRaysShader.js +4 -1
  246. package/examples/jsm/shaders/HalftoneShader.js +4 -1
  247. package/examples/jsm/shaders/HorizontalBlurShader.js +4 -1
  248. package/examples/jsm/shaders/HorizontalTiltShiftShader.js +4 -1
  249. package/examples/jsm/shaders/HueSaturationShader.js +4 -1
  250. package/examples/jsm/shaders/KaleidoShader.js +4 -1
  251. package/examples/jsm/shaders/LuminosityHighPassShader.js +4 -1
  252. package/examples/jsm/shaders/LuminosityShader.js +4 -1
  253. package/examples/jsm/shaders/MirrorShader.js +4 -1
  254. package/examples/jsm/shaders/NormalMapShader.js +4 -1
  255. package/examples/jsm/shaders/OutputShader.js +4 -1
  256. package/examples/jsm/shaders/PoissonDenoiseShader.js +4 -1
  257. package/examples/jsm/shaders/RGBShiftShader.js +4 -1
  258. package/examples/jsm/shaders/SAOShader.js +4 -1
  259. package/examples/jsm/shaders/SMAAShader.js +1 -0
  260. package/examples/jsm/shaders/SSAOShader.js +4 -1
  261. package/examples/jsm/shaders/SSRShader.js +1 -0
  262. package/examples/jsm/shaders/SepiaShader.js +4 -1
  263. package/examples/jsm/shaders/SobelOperatorShader.js +4 -1
  264. package/examples/jsm/shaders/SubsurfaceScatteringShader.js +4 -1
  265. package/examples/jsm/shaders/TechnicolorShader.js +4 -1
  266. package/examples/jsm/shaders/ToonShader.js +2 -1
  267. package/examples/jsm/shaders/TriangleBlurShader.js +4 -1
  268. package/examples/jsm/shaders/UnpackDepthRGBAShader.js +15 -3
  269. package/examples/jsm/shaders/VelocityShader.js +4 -1
  270. package/examples/jsm/shaders/VerticalBlurShader.js +4 -1
  271. package/examples/jsm/shaders/VerticalTiltShiftShader.js +4 -1
  272. package/examples/jsm/shaders/VignetteShader.js +4 -1
  273. package/examples/jsm/shaders/VolumeShader.js +5 -2
  274. package/examples/jsm/shaders/WaterRefractionShader.js +4 -1
  275. package/examples/jsm/textures/FlakesTexture.js +2 -0
  276. package/examples/jsm/transpiler/AST.js +381 -30
  277. package/examples/jsm/transpiler/GLSLDecoder.js +227 -88
  278. package/examples/jsm/transpiler/Linker.js +327 -0
  279. package/examples/jsm/transpiler/TSLEncoder.js +234 -85
  280. package/examples/jsm/transpiler/Transpiler.js +19 -1
  281. package/examples/jsm/transpiler/TranspilerUtils.js +29 -0
  282. package/examples/jsm/transpiler/WGSLEncoder.js +788 -0
  283. package/examples/jsm/tsl/display/AfterImageNode.js +2 -3
  284. package/examples/jsm/tsl/display/AnaglyphPassNode.js +1 -0
  285. package/examples/jsm/tsl/display/AnamorphicNode.js +5 -4
  286. package/examples/jsm/tsl/display/BloomNode.js +9 -7
  287. package/examples/jsm/tsl/display/ChromaticAberrationNode.js +206 -0
  288. package/examples/jsm/tsl/display/DenoiseNode.js +33 -33
  289. package/examples/jsm/tsl/display/DepthOfFieldNode.js +1 -0
  290. package/examples/jsm/tsl/display/DotScreenNode.js +1 -0
  291. package/examples/jsm/tsl/display/FXAANode.js +3 -2
  292. package/examples/jsm/tsl/display/FilmNode.js +1 -0
  293. package/examples/jsm/tsl/display/GTAONode.js +1 -0
  294. package/examples/jsm/tsl/display/GaussianBlurNode.js +9 -36
  295. package/examples/jsm/tsl/display/LensflareNode.js +1 -0
  296. package/examples/jsm/tsl/display/Lut3DNode.js +1 -0
  297. package/examples/jsm/tsl/display/OutlineNode.js +1 -0
  298. package/examples/jsm/tsl/display/ParallaxBarrierPassNode.js +1 -0
  299. package/examples/jsm/tsl/display/PixelationPassNode.js +1 -0
  300. package/examples/jsm/tsl/display/RGBShiftNode.js +1 -0
  301. package/examples/jsm/tsl/display/SMAANode.js +9 -8
  302. package/examples/jsm/tsl/display/SSAAPassNode.js +5 -4
  303. package/examples/jsm/tsl/display/SSRNode.js +1 -0
  304. package/examples/jsm/tsl/display/SobelOperatorNode.js +1 -0
  305. package/examples/jsm/tsl/display/StereoCompositePassNode.js +1 -0
  306. package/examples/jsm/tsl/display/StereoPassNode.js +1 -0
  307. package/examples/jsm/tsl/display/{TRAAPassNode.js → TRAANode.js} +184 -174
  308. package/examples/jsm/tsl/display/TransitionNode.js +1 -0
  309. package/examples/jsm/tsl/display/hashBlur.js +28 -6
  310. package/examples/jsm/tsl/lighting/TiledLightsNode.js +5 -4
  311. package/examples/jsm/tsl/math/Bayer.js +4 -1
  312. package/examples/jsm/tsl/shadows/TileShadowNode.js +456 -0
  313. package/examples/jsm/tsl/shadows/TileShadowNodeHelper.js +212 -0
  314. package/examples/jsm/tsl/utils/Raymarching.js +6 -3
  315. package/examples/jsm/utils/BufferGeometryUtils.js +4 -1
  316. package/examples/jsm/utils/CameraUtils.js +4 -1
  317. package/examples/jsm/utils/GeometryCompressionUtils.js +4 -1
  318. package/examples/jsm/utils/GeometryUtils.js +4 -1
  319. package/examples/jsm/utils/LDrawUtils.js +2 -0
  320. package/examples/jsm/utils/SceneOptimizer.js +2 -0
  321. package/examples/jsm/utils/SceneUtils.js +4 -1
  322. package/examples/jsm/utils/ShadowMapViewer.js +2 -0
  323. package/examples/jsm/utils/ShadowMapViewerGPU.js +2 -0
  324. package/examples/jsm/utils/SkeletonUtils.js +4 -1
  325. package/examples/jsm/utils/SortUtils.js +4 -1
  326. package/examples/jsm/utils/UVsDebug.js +4 -1
  327. package/examples/jsm/utils/WebGLTextureUtils.js +4 -1
  328. package/examples/jsm/utils/WebGPUTextureUtils.js +4 -1
  329. package/examples/jsm/utils/WorkerPool.js +2 -0
  330. package/examples/jsm/webxr/ARButton.js +1 -0
  331. package/examples/jsm/webxr/OculusHandModel.js +1 -0
  332. package/examples/jsm/webxr/OculusHandPointerModel.js +1 -0
  333. package/examples/jsm/webxr/Text2D.js +4 -1
  334. package/examples/jsm/webxr/VRButton.js +1 -0
  335. package/examples/jsm/webxr/XRButton.js +1 -0
  336. package/examples/jsm/webxr/XRControllerModelFactory.js +2 -0
  337. package/examples/jsm/webxr/XREstimatedLight.js +1 -0
  338. package/examples/jsm/webxr/XRHandMeshModel.js +2 -0
  339. package/examples/jsm/webxr/XRHandModelFactory.js +2 -0
  340. package/examples/jsm/webxr/XRHandPrimitiveModel.js +2 -0
  341. package/examples/jsm/webxr/XRPlanes.js +1 -0
  342. package/package.json +6 -4
  343. package/src/Three.Core.js +2 -1
  344. package/src/Three.TSL.js +83 -26
  345. package/src/Three.WebGPU.Nodes.js +1 -0
  346. package/src/Three.WebGPU.js +3 -0
  347. package/src/animation/KeyframeTrack.js +1 -1
  348. package/src/animation/tracks/BooleanKeyframeTrack.js +1 -1
  349. package/src/animation/tracks/StringKeyframeTrack.js +1 -1
  350. package/src/audio/AudioListener.js +13 -10
  351. package/src/cameras/ArrayCamera.js +9 -1
  352. package/src/cameras/Camera.js +14 -0
  353. package/src/cameras/OrthographicCamera.js +1 -1
  354. package/src/cameras/PerspectiveCamera.js +1 -1
  355. package/src/constants.js +47 -20
  356. package/src/core/BufferAttribute.js +3 -3
  357. package/src/core/BufferGeometry.js +2 -5
  358. package/src/core/Clock.js +2 -8
  359. package/src/core/GLBufferAttribute.js +13 -1
  360. package/src/core/Object3D.js +23 -22
  361. package/src/core/RenderTarget.js +65 -21
  362. package/src/core/RenderTarget3D.js +1 -0
  363. package/{examples/jsm/misc → src/core}/Timer.js +4 -40
  364. package/src/extras/PMREMGenerator.js +11 -0
  365. package/src/extras/TextureUtils.js +1 -5
  366. package/src/extras/core/Curve.js +1 -1
  367. package/src/extras/core/Path.js +22 -22
  368. package/src/geometries/CapsuleGeometry.js +167 -17
  369. package/src/geometries/ExtrudeGeometry.js +39 -29
  370. package/src/helpers/ArrowHelper.js +2 -2
  371. package/src/helpers/CameraHelper.js +41 -11
  372. package/src/helpers/SkeletonHelper.js +36 -7
  373. package/src/lights/LightShadow.js +34 -7
  374. package/src/lights/PointLightShadow.js +1 -1
  375. package/src/lights/SpotLightShadow.js +9 -1
  376. package/src/lights/webgpu/ProjectorLight.js +46 -0
  377. package/src/loaders/BufferGeometryLoader.js +1 -10
  378. package/src/loaders/FileLoader.js +27 -4
  379. package/src/loaders/ImageBitmapLoader.js +48 -9
  380. package/src/loaders/ImageLoader.js +55 -8
  381. package/src/loaders/Loader.js +14 -0
  382. package/src/loaders/LoadingManager.js +23 -0
  383. package/src/loaders/ObjectLoader.js +44 -16
  384. package/src/loaders/nodes/NodeObjectLoader.js +2 -2
  385. package/src/materials/Material.js +1 -7
  386. package/src/materials/MeshBasicMaterial.js +1 -1
  387. package/src/materials/nodes/Line2NodeMaterial.js +0 -8
  388. package/src/materials/nodes/MeshBasicNodeMaterial.js +4 -3
  389. package/src/materials/nodes/MeshMatcapNodeMaterial.js +1 -1
  390. package/src/materials/nodes/MeshNormalNodeMaterial.js +2 -2
  391. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +2 -1
  392. package/src/materials/nodes/MeshSSSNodeMaterial.js +2 -2
  393. package/src/materials/nodes/NodeMaterial.js +106 -20
  394. package/src/materials/nodes/PointsNodeMaterial.js +5 -0
  395. package/src/materials/nodes/manager/NodeMaterialObserver.js +107 -4
  396. package/src/math/Box3.js +28 -0
  397. package/src/math/Color.js +7 -7
  398. package/src/math/ColorManagement.js +22 -3
  399. package/src/math/Frustum.js +25 -9
  400. package/src/math/FrustumArray.js +258 -0
  401. package/src/math/Line3.js +129 -2
  402. package/src/math/Matrix4.js +48 -27
  403. package/src/math/Quaternion.js +1 -1
  404. package/src/math/Ray.js +2 -0
  405. package/src/math/Sphere.js +28 -0
  406. package/src/math/Spherical.js +2 -2
  407. package/src/nodes/Nodes.js +3 -3
  408. package/src/nodes/TSL.js +6 -3
  409. package/src/nodes/accessors/AccessorsUtils.js +7 -8
  410. package/src/nodes/accessors/Bitangent.js +54 -26
  411. package/src/nodes/accessors/Camera.js +40 -13
  412. package/src/nodes/accessors/CubeTextureNode.js +50 -2
  413. package/src/nodes/accessors/InstanceNode.js +5 -4
  414. package/src/nodes/accessors/Lights.js +2 -2
  415. package/src/nodes/accessors/MaterialNode.js +4 -0
  416. package/src/nodes/accessors/ModelNode.js +1 -1
  417. package/src/nodes/accessors/Normal.js +110 -24
  418. package/src/nodes/accessors/Object3DNode.js +7 -8
  419. package/src/nodes/accessors/Position.js +14 -4
  420. package/src/nodes/accessors/ReferenceBaseNode.js +1 -1
  421. package/src/nodes/accessors/ReferenceNode.js +19 -4
  422. package/src/nodes/accessors/ReflectVector.js +3 -3
  423. package/src/nodes/accessors/SceneNode.js +1 -1
  424. package/src/nodes/accessors/SkinningNode.js +3 -2
  425. package/src/nodes/accessors/StorageBufferNode.js +25 -0
  426. package/src/nodes/accessors/StorageTextureNode.js +15 -4
  427. package/src/nodes/accessors/Tangent.js +25 -17
  428. package/src/nodes/accessors/TangentUtils.js +46 -0
  429. package/src/nodes/accessors/TextureBicubic.js +21 -3
  430. package/src/nodes/accessors/TextureNode.js +71 -8
  431. package/src/nodes/accessors/UniformArrayNode.js +0 -16
  432. package/src/nodes/accessors/VelocityNode.js +1 -0
  433. package/src/nodes/accessors/VertexColorNode.js +4 -4
  434. package/src/nodes/code/CodeNode.js +8 -11
  435. package/src/nodes/core/ArrayNode.js +12 -0
  436. package/src/nodes/core/AssignNode.js +30 -5
  437. package/src/nodes/core/AttributeNode.js +2 -2
  438. package/src/nodes/core/ContextNode.js +27 -4
  439. package/src/nodes/core/Node.js +83 -22
  440. package/src/nodes/core/NodeBuilder.js +273 -49
  441. package/src/nodes/core/NodeUtils.js +46 -1
  442. package/src/nodes/core/NodeVarying.js +19 -1
  443. package/src/nodes/core/PropertyNode.js +8 -12
  444. package/src/nodes/core/StackNode.js +171 -26
  445. package/src/nodes/core/StructTypeNode.js +26 -4
  446. package/src/nodes/core/SubBuildNode.js +89 -0
  447. package/src/nodes/core/UniformNode.js +63 -5
  448. package/src/nodes/core/VarNode.js +102 -4
  449. package/src/nodes/core/VaryingNode.js +45 -24
  450. package/src/nodes/display/BlendModes.js +42 -1
  451. package/src/nodes/display/ColorSpaceNode.js +4 -27
  452. package/src/nodes/display/FrontFacingNode.js +34 -2
  453. package/src/nodes/display/NormalMapNode.js +19 -50
  454. package/src/nodes/display/PassNode.js +165 -20
  455. package/src/nodes/display/ScreenNode.js +0 -26
  456. package/src/nodes/display/ViewportTextureNode.js +67 -7
  457. package/src/nodes/functions/BSDF/BRDF_GGX.js +2 -6
  458. package/src/nodes/functions/BSDF/BRDF_Sheen.js +4 -4
  459. package/src/nodes/functions/PhongLightingModel.js +3 -3
  460. package/src/nodes/functions/PhysicalLightingModel.js +16 -16
  461. package/src/nodes/functions/ShadowMaskModel.js +5 -1
  462. package/src/nodes/functions/material/getGeometryRoughness.js +2 -2
  463. package/src/nodes/functions/material/getParallaxCorrectNormal.js +1 -1
  464. package/src/nodes/gpgpu/AtomicFunctionNode.js +28 -10
  465. package/src/nodes/gpgpu/BarrierNode.js +3 -3
  466. package/src/nodes/gpgpu/ComputeNode.js +68 -24
  467. package/src/nodes/gpgpu/WorkgroupInfoNode.js +28 -3
  468. package/src/nodes/lighting/AnalyticLightNode.js +7 -13
  469. package/src/nodes/lighting/EnvironmentNode.js +5 -5
  470. package/src/nodes/lighting/HemisphereLightNode.js +2 -2
  471. package/src/nodes/lighting/IESSpotLightNode.js +2 -1
  472. package/src/nodes/lighting/LightsNode.js +29 -11
  473. package/src/nodes/lighting/ProjectorLightNode.js +91 -0
  474. package/src/nodes/lighting/ShadowBaseNode.js +1 -12
  475. package/src/nodes/lighting/ShadowFilterNode.js +274 -0
  476. package/src/nodes/lighting/ShadowNode.js +174 -242
  477. package/src/nodes/lighting/SpotLightNode.js +44 -7
  478. package/src/nodes/materialx/MaterialXNodes.js +131 -2
  479. package/src/nodes/materialx/lib/mx_noise.js +166 -2
  480. package/src/nodes/math/ConditionalNode.js +1 -20
  481. package/src/nodes/math/MathNode.js +146 -75
  482. package/src/nodes/math/OperatorNode.js +129 -119
  483. package/src/nodes/shapes/Shapes.js +5 -4
  484. package/src/nodes/tsl/TSLBase.js +1 -0
  485. package/src/nodes/tsl/TSLCore.js +222 -72
  486. package/src/nodes/utils/DebugNode.js +16 -4
  487. package/src/nodes/utils/Discard.js +2 -2
  488. package/src/nodes/utils/EquirectUV.js +27 -0
  489. package/src/nodes/utils/EventNode.js +83 -0
  490. package/src/nodes/utils/LoopNode.js +64 -34
  491. package/src/nodes/utils/MatcapUV.js +22 -0
  492. package/src/nodes/utils/RTTNode.js +22 -5
  493. package/src/nodes/utils/ReflectorNode.js +77 -7
  494. package/src/nodes/utils/SampleNode.js +81 -0
  495. package/src/nodes/utils/TriplanarTextures.js +65 -0
  496. package/src/objects/BatchedMesh.js +20 -6
  497. package/src/objects/Mesh.js +9 -0
  498. package/src/objects/Skeleton.js +1 -1
  499. package/src/objects/Sprite.js +9 -0
  500. package/src/renderers/WebGL3DRenderTarget.js +1 -0
  501. package/src/renderers/WebGLArrayRenderTarget.js +1 -0
  502. package/src/renderers/WebGLCubeRenderTarget.js +2 -4
  503. package/src/renderers/WebGLRenderer.js +45 -32
  504. package/src/renderers/common/Animation.js +2 -2
  505. package/src/renderers/common/Background.js +13 -2
  506. package/src/renderers/common/Bindings.js +19 -18
  507. package/src/renderers/common/Color4.js +2 -2
  508. package/src/renderers/common/CubeRenderTarget.js +1 -1
  509. package/src/renderers/common/PostProcessing.js +60 -5
  510. package/src/renderers/common/RenderList.js +0 -4
  511. package/src/renderers/common/RenderObject.js +80 -4
  512. package/src/renderers/common/Renderer.js +133 -22
  513. package/src/renderers/common/SampledTexture.js +3 -71
  514. package/src/renderers/common/Sampler.js +79 -0
  515. package/src/renderers/common/Storage3DTexture.js +100 -0
  516. package/src/renderers/common/StorageArrayTexture.js +84 -0
  517. package/src/renderers/common/StorageTexture.js +19 -0
  518. package/src/renderers/common/Textures.js +34 -24
  519. package/src/renderers/common/TimestampQueryPool.js +1 -0
  520. package/src/renderers/common/Uniform.js +1 -1
  521. package/src/renderers/common/UniformsGroup.js +14 -18
  522. package/src/renderers/common/XRManager.js +183 -35
  523. package/src/renderers/common/XRRenderTarget.js +21 -4
  524. package/src/renderers/common/extras/PMREMGenerator.js +30 -23
  525. package/src/renderers/common/nodes/NodeSampledTexture.js +0 -12
  526. package/src/renderers/common/nodes/Nodes.js +13 -3
  527. package/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js +1 -1
  528. package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +20 -2
  529. package/src/renderers/shaders/ShaderLib/background.glsl.js +1 -1
  530. package/src/renderers/shaders/ShaderLib/depth.glsl.js +11 -2
  531. package/src/renderers/webgl/WebGLAttributes.js +4 -0
  532. package/src/renderers/webgl/WebGLCapabilities.js +2 -2
  533. package/src/renderers/webgl/WebGLMaterials.js +6 -6
  534. package/src/renderers/webgl/WebGLProgram.js +22 -16
  535. package/src/renderers/webgl/WebGLPrograms.js +8 -6
  536. package/src/renderers/webgl/WebGLShadowMap.js +14 -3
  537. package/src/renderers/webgl/WebGLState.js +4 -4
  538. package/src/renderers/webgl/WebGLTextures.js +163 -11
  539. package/src/renderers/webgl/WebGLUtils.js +1 -3
  540. package/src/renderers/webgl-fallback/WebGLBackend.js +261 -94
  541. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +75 -9
  542. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +4 -0
  543. package/src/renderers/webgl-fallback/utils/WebGLConstants.js +1 -0
  544. package/src/renderers/webgl-fallback/utils/WebGLState.js +4 -4
  545. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +44 -29
  546. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +22 -21
  547. package/src/renderers/webgpu/WebGPUBackend.js +505 -143
  548. package/src/renderers/webgpu/WebGPURenderer.js +7 -0
  549. package/src/renderers/webgpu/nodes/BasicNodeLibrary.js +4 -1
  550. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +4 -1
  551. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +129 -96
  552. package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +3 -0
  553. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +9 -1
  554. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +58 -31
  555. package/src/renderers/webgpu/utils/WebGPUConstants.js +8 -2
  556. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +39 -9
  557. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +50 -108
  558. package/src/renderers/webgpu/utils/WebGPUUtils.js +2 -17
  559. package/src/renderers/webxr/WebXRController.js +1 -1
  560. package/src/renderers/webxr/WebXRDepthSensing.js +6 -10
  561. package/src/renderers/webxr/WebXRManager.js +70 -9
  562. package/src/textures/DepthTexture.js +6 -10
  563. package/src/textures/ExternalTexture.js +45 -0
  564. package/src/textures/FramebufferTexture.js +2 -2
  565. package/src/textures/Source.js +32 -0
  566. package/src/textures/Texture.js +118 -1
  567. package/src/textures/VideoTexture.js +31 -3
  568. package/examples/jsm/effects/PeppersGhostEffect.js +0 -172
  569. package/src/core/RenderTargetArray.js +0 -40
  570. package/src/nodes/utils/EquirectUVNode.js +0 -65
  571. package/src/nodes/utils/MatcapUVNode.js +0 -49
  572. package/src/nodes/utils/TriplanarTexturesNode.js +0 -148
@@ -9,6 +9,121 @@ import {
9
9
  zipSync,
10
10
  } from '../libs/fflate.module.js';
11
11
 
12
+ class USDNode {
13
+
14
+ constructor( name, type = '', metadata = [], properties = [] ) {
15
+
16
+ this.name = name;
17
+ this.type = type;
18
+ this.metadata = metadata;
19
+ this.properties = properties;
20
+ this.children = [];
21
+
22
+ }
23
+
24
+ addMetadata( key, value ) {
25
+
26
+ this.metadata.push( { key, value } );
27
+
28
+ }
29
+
30
+ addProperty( property, metadata = [] ) {
31
+
32
+ this.properties.push( { property, metadata } );
33
+
34
+ }
35
+
36
+ addChild( child ) {
37
+
38
+ this.children.push( child );
39
+
40
+ }
41
+
42
+ toString( indent = 0 ) {
43
+
44
+ const pad = '\t'.repeat( indent );
45
+
46
+ const formattedMetadata = this.metadata.map( ( item ) => {
47
+
48
+ const key = item.key;
49
+ const value = item.value;
50
+
51
+ if ( Array.isArray( value ) ) {
52
+
53
+ const lines = [];
54
+ lines.push( `${key} = {` );
55
+ value.forEach( ( line ) => {
56
+
57
+ lines.push( `${pad}\t\t${line}` );
58
+
59
+ } );
60
+ lines.push( `${pad}\t}` );
61
+ return lines.join( '\n' );
62
+
63
+ } else {
64
+
65
+ return `${key} = ${value}`;
66
+
67
+ }
68
+
69
+ } );
70
+
71
+ const meta = formattedMetadata.length
72
+ ? ` (\n${formattedMetadata
73
+ .map( ( l ) => `${pad}\t${l}` )
74
+ .join( '\n' )}\n${pad})`
75
+ : '';
76
+
77
+ const properties = this.properties.map( ( l ) => {
78
+
79
+ const property = l.property;
80
+ const metadata = l.metadata.length
81
+ ? ` (\n${l.metadata.map( ( m ) => `${pad}\t\t${m}` ).join( '\n' )}\n${pad}\t)`
82
+ : '';
83
+ return `${pad}\t${property}${metadata}`;
84
+
85
+ } );
86
+ const children = this.children.map( ( c ) => c.toString( indent + 1 ) );
87
+
88
+ const bodyLines = [];
89
+
90
+ if ( properties.length > 0 ) {
91
+
92
+ bodyLines.push( ...properties );
93
+
94
+ }
95
+
96
+ if ( children.length > 0 ) {
97
+
98
+ if ( properties.length > 0 ) {
99
+
100
+ bodyLines.push( '' );
101
+
102
+ }
103
+
104
+ for ( let i = 0; i < children.length; i ++ ) {
105
+
106
+ bodyLines.push( children[ i ] );
107
+ if ( i < children.length - 1 ) {
108
+
109
+ bodyLines.push( '' );
110
+
111
+ }
112
+
113
+ }
114
+
115
+ }
116
+
117
+ const bodyContent = bodyLines.join( '\n' );
118
+
119
+ const type = this.type ? this.type + ' ' : '';
120
+
121
+ return `${pad}def ${type}"${this.name}"${meta}\n${pad}{\n${bodyContent}\n${pad}}`;
122
+
123
+ }
124
+
125
+ }
126
+
12
127
  /**
13
128
  * An exporter for USDZ.
14
129
  *
@@ -16,6 +131,8 @@ import {
16
131
  * const exporter = new USDZExporter();
17
132
  * const arraybuffer = await exporter.parseAsync( scene );
18
133
  * ```
134
+ *
135
+ * @three_import import { USDZExporter } from 'three/addons/exporters/USDZExporter.js';
19
136
  */
20
137
  class USDZExporter {
21
138
 
@@ -72,15 +189,21 @@ class USDZExporter {
72
189
  */
73
190
  async parseAsync( scene, options = {} ) {
74
191
 
75
- options = Object.assign( {
76
- ar: {
77
- anchoring: { type: 'plane' },
78
- planeAnchoring: { alignment: 'horizontal' }
192
+ options = Object.assign(
193
+ {
194
+ ar: {
195
+ anchoring: { type: 'plane' },
196
+ planeAnchoring: { alignment: 'horizontal' },
197
+ },
198
+ includeAnchoringProperties: true,
199
+ onlyVisible: true,
200
+ quickLookCompatible: false,
201
+ maxTextureSize: 1024,
79
202
  },
80
- includeAnchoringProperties: true,
81
- quickLookCompatible: false,
82
- maxTextureSize: 1024,
83
- }, options );
203
+ options
204
+ );
205
+
206
+ const usedNames = new Set();
84
207
 
85
208
  const files = {};
86
209
  const modelFileName = 'model.usda';
@@ -88,57 +211,50 @@ class USDZExporter {
88
211
  // model file should be first in USDZ archive so we init it here
89
212
  files[ modelFileName ] = null;
90
213
 
91
- let output = buildHeader();
92
-
93
- output += buildSceneStart( options );
94
-
95
- const materials = {};
96
- const textures = {};
97
-
98
- scene.traverseVisible( ( object ) => {
99
-
100
- if ( object.isMesh ) {
101
-
102
- const geometry = object.geometry;
103
- const material = object.material;
104
-
105
- if ( material.isMeshStandardMaterial ) {
106
-
107
- const geometryFileName = 'geometries/Geometry_' + geometry.id + '.usda';
108
-
109
- if ( ! ( geometryFileName in files ) ) {
110
-
111
- const meshObject = buildMeshObject( geometry );
112
- files[ geometryFileName ] = buildUSDFileAsString( meshObject );
214
+ const root = new USDNode( 'Root', 'Xform' );
215
+ const scenesNode = new USDNode( 'Scenes', 'Scope' );
216
+ scenesNode.addMetadata( 'kind', '"sceneLibrary"' );
217
+ root.addChild( scenesNode );
218
+
219
+ const sceneName = 'Scene';
220
+ const sceneNode = new USDNode( sceneName, 'Xform' );
221
+ sceneNode.addMetadata( 'customData', [
222
+ 'bool preliminary_collidesWithEnvironment = 0',
223
+ `string sceneName = "${sceneName}"`,
224
+ ] );
225
+ sceneNode.addMetadata( 'sceneName', `"${sceneName}"` );
226
+ if ( options.includeAnchoringProperties ) {
227
+
228
+ sceneNode.addProperty(
229
+ `token preliminary:anchoring:type = "${options.ar.anchoring.type}"`
230
+ );
231
+ sceneNode.addProperty(
232
+ `token preliminary:planeAnchoring:alignment = "${options.ar.planeAnchoring.alignment}"`
233
+ );
113
234
 
114
- }
115
-
116
- if ( ! ( material.uuid in materials ) ) {
117
-
118
- materials[ material.uuid ] = material;
119
-
120
- }
121
-
122
- output += buildXform( object, geometry, materials[ material.uuid ] );
123
-
124
- } else {
125
-
126
- console.warn( 'THREE.USDZExporter: Unsupported material type (USDZ only supports MeshStandardMaterial)', object );
127
-
128
- }
129
-
130
- } else if ( object.isCamera ) {
235
+ }
131
236
 
132
- output += buildCamera( object );
237
+ scenesNode.addChild( sceneNode );
133
238
 
134
- }
239
+ let output;
135
240
 
136
- } );
241
+ const materials = {};
242
+ const textures = {};
137
243
 
244
+ buildHierarchy( scene, sceneNode, materials, usedNames, files, options );
138
245
 
139
- output += buildSceneEnd();
246
+ const materialsNode = buildMaterials(
247
+ materials,
248
+ textures,
249
+ options.quickLookCompatible
250
+ );
140
251
 
141
- output += buildMaterials( materials, textures, options.quickLookCompatible );
252
+ output =
253
+ buildHeader() +
254
+ '\n' +
255
+ root.toString() +
256
+ '\n\n' +
257
+ materialsNode.toString();
142
258
 
143
259
  files[ modelFileName ] = strToU8( output );
144
260
  output = null;
@@ -151,7 +267,9 @@ class USDZExporter {
151
267
 
152
268
  if ( this.textureUtils === null ) {
153
269
 
154
- throw new Error( 'THREE.USDZExporter: setTextureUtils() must be called to process compressed textures.' );
270
+ throw new Error(
271
+ 'THREE.USDZExporter: setTextureUtils() must be called to process compressed textures.'
272
+ );
155
273
 
156
274
  } else {
157
275
 
@@ -161,10 +279,18 @@ class USDZExporter {
161
279
 
162
280
  }
163
281
 
164
- const canvas = imageToCanvas( texture.image, texture.flipY, options.maxTextureSize );
165
- const blob = await new Promise( resolve => canvas.toBlob( resolve, 'image/png', 1 ) );
282
+ const canvas = imageToCanvas(
283
+ texture.image,
284
+ texture.flipY,
285
+ options.maxTextureSize
286
+ );
287
+ const blob = await new Promise( ( resolve ) =>
288
+ canvas.toBlob( resolve, 'image/png', 1 )
289
+ );
166
290
 
167
- files[ `textures/Texture_${ id }.png` ] = new Uint8Array( await blob.arrayBuffer() );
291
+ files[ `textures/Texture_${id}.png` ] = new Uint8Array(
292
+ await blob.arrayBuffer()
293
+ );
168
294
 
169
295
  }
170
296
 
@@ -201,12 +327,53 @@ class USDZExporter {
201
327
 
202
328
  }
203
329
 
330
+ function getName( object, namesSet ) {
331
+
332
+ let name = object.name;
333
+ name = name.replace( /[^A-Za-z0-9_]/g, '' );
334
+ if ( /^[0-9]/.test( name ) ) {
335
+
336
+ name = '_' + name;
337
+
338
+ }
339
+
340
+ if ( name === '' ) {
341
+
342
+ if ( object.isCamera ) {
343
+
344
+ name = 'Camera';
345
+
346
+ } else {
347
+
348
+ name = 'Object';
349
+
350
+ }
351
+
352
+ }
353
+
354
+ if ( namesSet.has( name ) ) {
355
+
356
+ name = name + '_' + object.id;
357
+
358
+ }
359
+
360
+ namesSet.add( name );
361
+
362
+ return name;
363
+
364
+ }
365
+
204
366
  function imageToCanvas( image, flipY, maxTextureSize ) {
205
367
 
206
- if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
207
- ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
208
- ( typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas ) ||
209
- ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
368
+ if (
369
+ ( typeof HTMLImageElement !== 'undefined' &&
370
+ image instanceof HTMLImageElement ) ||
371
+ ( typeof HTMLCanvasElement !== 'undefined' &&
372
+ image instanceof HTMLCanvasElement ) ||
373
+ ( typeof OffscreenCanvas !== 'undefined' &&
374
+ image instanceof OffscreenCanvas ) ||
375
+ ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap )
376
+ ) {
210
377
 
211
378
  const scale = maxTextureSize / Math.max( image.width, image.height );
212
379
 
@@ -231,7 +398,9 @@ function imageToCanvas( image, flipY, maxTextureSize ) {
231
398
 
232
399
  } else {
233
400
 
234
- throw new Error( 'THREE.USDZExporter: No valid image data found. Unable to process texture.' );
401
+ throw new Error(
402
+ 'THREE.USDZExporter: No valid image data found. Unable to process texture.'
403
+ );
235
404
 
236
405
  }
237
406
 
@@ -252,79 +421,121 @@ function buildHeader() {
252
421
  metersPerUnit = 1
253
422
  upAxis = "Y"
254
423
  )
255
-
256
424
  `;
257
425
 
258
426
  }
259
427
 
260
- function buildSceneStart( options ) {
261
-
262
- const alignment = options.includeAnchoringProperties === true ? `
263
- token preliminary:anchoring:type = "${options.ar.anchoring.type}"
264
- token preliminary:planeAnchoring:alignment = "${options.ar.planeAnchoring.alignment}"
265
- ` : '';
266
- return `def Xform "Root"
267
- {
268
- def Scope "Scenes" (
269
- kind = "sceneLibrary"
270
- )
271
- {
272
- def Xform "Scene" (
273
- customData = {
274
- bool preliminary_collidesWithEnvironment = 0
275
- string sceneName = "Scene"
428
+ // Xform
429
+
430
+ function buildHierarchy( object, parentNode, materials, usedNames, files, options ) {
431
+
432
+ for ( let i = 0, l = object.children.length; i < l; i ++ ) {
433
+
434
+ const child = object.children[ i ];
435
+
436
+ if ( child.visible === false && options.onlyVisible === true ) continue;
437
+
438
+ let childNode;
439
+
440
+ if ( child.isMesh ) {
441
+
442
+ const geometry = child.geometry;
443
+ const material = child.material;
444
+
445
+ if ( material.isMeshStandardMaterial ) {
446
+
447
+ const geometryFileName = 'geometries/Geometry_' + geometry.id + '.usda';
448
+
449
+ if ( ! ( geometryFileName in files ) ) {
450
+
451
+ const meshObject = buildMeshObject( geometry );
452
+ files[ geometryFileName ] = strToU8(
453
+ buildHeader() + '\n' + meshObject.toString()
454
+ );
455
+
456
+ }
457
+
458
+ if ( ! ( material.uuid in materials ) ) {
459
+
460
+ materials[ material.uuid ] = material;
461
+
462
+ }
463
+
464
+ childNode = buildMesh(
465
+ child,
466
+ geometry,
467
+ materials[ material.uuid ],
468
+ usedNames
469
+ );
470
+
471
+ } else {
472
+
473
+ console.warn(
474
+ 'THREE.USDZExporter: Unsupported material type (USDZ only supports MeshStandardMaterial)',
475
+ child
476
+ );
477
+
276
478
  }
277
- sceneName = "Scene"
278
- )
279
- {${alignment}
280
- `;
281
479
 
282
- }
480
+ } else if ( child.isCamera ) {
283
481
 
284
- function buildSceneEnd() {
482
+ childNode = buildCamera( child, usedNames );
483
+
484
+ } else {
485
+
486
+ childNode = buildXform( child, usedNames );
285
487
 
286
- return `
287
488
  }
288
- }
289
- }
290
489
 
291
- `;
490
+ if ( childNode ) {
292
491
 
293
- }
492
+ parentNode.addChild( childNode );
493
+ buildHierarchy( child, childNode, materials, usedNames, files, options );
294
494
 
295
- function buildUSDFileAsString( dataToInsert ) {
495
+ }
296
496
 
297
- let output = buildHeader();
298
- output += dataToInsert;
299
- return strToU8( output );
497
+ }
300
498
 
301
499
  }
302
500
 
303
- // Xform
304
-
305
- function buildXform( object, geometry, material ) {
501
+ function buildXform( object, usedNames ) {
306
502
 
307
- const name = 'Object_' + object.id;
308
- const transform = buildMatrix( object.matrixWorld );
503
+ const name = getName( object, usedNames );
504
+ const transform = buildMatrix( object.matrix );
309
505
 
310
- if ( object.matrixWorld.determinant() < 0 ) {
506
+ if ( object.matrix.determinant() < 0 ) {
311
507
 
312
- console.warn( 'THREE.USDZExporter: USDZ does not support negative scales', object );
508
+ console.warn(
509
+ 'THREE.USDZExporter: USDZ does not support negative scales',
510
+ object
511
+ );
313
512
 
314
513
  }
315
514
 
316
- return `def Xform "${ name }" (
317
- prepend references = @./geometries/Geometry_${ geometry.id }.usda@</Geometry>
318
- prepend apiSchemas = ["MaterialBindingAPI"]
319
- )
320
- {
321
- matrix4d xformOp:transform = ${ transform }
322
- uniform token[] xformOpOrder = ["xformOp:transform"]
515
+ const node = new USDNode( name, 'Xform' );
516
+
517
+ node.addProperty( `matrix4d xformOp:transform = ${transform}` );
518
+ node.addProperty( 'uniform token[] xformOpOrder = ["xformOp:transform"]' );
519
+
520
+ return node;
323
521
 
324
- rel material:binding = </Materials/Material_${ material.id }>
325
522
  }
326
523
 
327
- `;
524
+ function buildMesh( object, geometry, material, usedNames ) {
525
+
526
+ const node = buildXform( object, usedNames );
527
+
528
+ node.addMetadata(
529
+ 'prepend references',
530
+ `@./geometries/Geometry_${geometry.id}.usda@</Geometry>`
531
+ );
532
+ node.addMetadata( 'prepend apiSchemas', '["MaterialBindingAPI"]' );
533
+
534
+ node.addProperty(
535
+ `rel material:binding = </Materials/Material_${material.id}>`
536
+ );
537
+
538
+ return node;
328
539
 
329
540
  }
330
541
 
@@ -332,13 +543,18 @@ function buildMatrix( matrix ) {
332
543
 
333
544
  const array = matrix.elements;
334
545
 
335
- return `( ${ buildMatrixRow( array, 0 ) }, ${ buildMatrixRow( array, 4 ) }, ${ buildMatrixRow( array, 8 ) }, ${ buildMatrixRow( array, 12 ) } )`;
546
+ return `( ${buildMatrixRow( array, 0 )}, ${buildMatrixRow(
547
+ array,
548
+ 4
549
+ )}, ${buildMatrixRow( array, 8 )}, ${buildMatrixRow( array, 12 )} )`;
336
550
 
337
551
  }
338
552
 
339
553
  function buildMatrixRow( array, offset ) {
340
554
 
341
- return `(${ array[ offset + 0 ] }, ${ array[ offset + 1 ] }, ${ array[ offset + 2 ] }, ${ array[ offset + 3 ] })`;
555
+ return `(${array[ offset + 0 ]}, ${array[ offset + 1 ]}, ${array[ offset + 2 ]}, ${
556
+ array[ offset + 3 ]
557
+ })`;
342
558
 
343
559
  }
344
560
 
@@ -346,43 +562,81 @@ function buildMatrixRow( array, offset ) {
346
562
 
347
563
  function buildMeshObject( geometry ) {
348
564
 
349
- const mesh = buildMesh( geometry );
350
- return `
351
- def "Geometry"
352
- {
353
- ${mesh}
354
- }
355
- `;
565
+ const node = new USDNode( 'Geometry' );
566
+
567
+ const meshNode = buildMeshNode( geometry );
568
+ node.addChild( meshNode );
569
+
570
+ return node;
356
571
 
357
572
  }
358
573
 
359
- function buildMesh( geometry ) {
574
+ function buildMeshNode( geometry ) {
360
575
 
361
576
  const name = 'Geometry';
362
577
  const attributes = geometry.attributes;
363
578
  const count = attributes.position.count;
364
579
 
365
- return `
366
- def Mesh "${ name }"
367
- {
368
- int[] faceVertexCounts = [${ buildMeshVertexCount( geometry ) }]
369
- int[] faceVertexIndices = [${ buildMeshVertexIndices( geometry ) }]
370
- normal3f[] normals = [${ buildVector3Array( attributes.normal, count )}] (
371
- interpolation = "vertex"
372
- )
373
- point3f[] points = [${ buildVector3Array( attributes.position, count )}]
374
- ${ buildPrimvars( attributes ) }
375
- uniform token subdivisionScheme = "none"
580
+ const node = new USDNode( name, 'Mesh' );
581
+
582
+ node.addProperty(
583
+ `int[] faceVertexCounts = [${buildMeshVertexCount( geometry )}]`
584
+ );
585
+ node.addProperty(
586
+ `int[] faceVertexIndices = [${buildMeshVertexIndices( geometry )}]`
587
+ );
588
+ node.addProperty(
589
+ `normal3f[] normals = [${buildVector3Array( attributes.normal, count )}]`,
590
+ [ 'interpolation = "vertex"' ]
591
+ );
592
+ node.addProperty(
593
+ `point3f[] points = [${buildVector3Array( attributes.position, count )}]`
594
+ );
595
+
596
+ for ( let i = 0; i < 4; i ++ ) {
597
+
598
+ const id = i > 0 ? i : '';
599
+ const attribute = attributes[ 'uv' + id ];
600
+ if ( attribute !== undefined ) {
601
+
602
+ node.addProperty(
603
+ `texCoord2f[] primvars:st${id} = [${buildVector2Array( attribute )}]`,
604
+ [ 'interpolation = "vertex"' ]
605
+ );
606
+
607
+ }
608
+
376
609
  }
377
- `;
610
+
611
+ const colorAttribute = attributes.color;
612
+ if ( colorAttribute !== undefined ) {
613
+
614
+ node.addProperty(
615
+ `color3f[] primvars:displayColor = [${buildVector3Array(
616
+ colorAttribute,
617
+ count
618
+ )}]`,
619
+ [ 'interpolation = "vertex"' ]
620
+ );
621
+
622
+ }
623
+
624
+ node.addProperty( 'uniform token subdivisionScheme = "none"' );
625
+
626
+ return node;
378
627
 
379
628
  }
380
629
 
381
630
  function buildMeshVertexCount( geometry ) {
382
631
 
383
- const count = geometry.index !== null ? geometry.index.count : geometry.attributes.position.count;
632
+ const count =
633
+ geometry.index !== null
634
+ ? geometry.index.count
635
+ : geometry.attributes.position.count;
384
636
 
385
- return Array( count / 3 ).fill( 3 ).join( ', ' );
637
+ return Array( count / 3 )
638
+ .fill( 3 )
639
+ .join( ', ' );
386
640
 
387
641
  }
388
642
 
@@ -432,7 +686,11 @@ function buildVector3Array( attribute, count ) {
432
686
  const y = attribute.getY( i );
433
687
  const z = attribute.getZ( i );
434
688
 
435
- array.push( `(${ x.toPrecision( PRECISION ) }, ${ y.toPrecision( PRECISION ) }, ${ z.toPrecision( PRECISION ) })` );
689
+ array.push(
690
+ `(${x.toPrecision( PRECISION )}, ${y.toPrecision(
691
+ PRECISION
692
+ )}, ${z.toPrecision( PRECISION )})`
693
+ );
436
694
 
437
695
  }
438
696
 
@@ -449,7 +707,9 @@ function buildVector2Array( attribute ) {
449
707
  const x = attribute.getX( i );
450
708
  const y = attribute.getY( i );
451
709
 
452
- array.push( `(${ x.toPrecision( PRECISION ) }, ${ 1 - y.toPrecision( PRECISION ) })` );
710
+ array.push(
711
+ `(${x.toPrecision( PRECISION )}, ${1 - y.toPrecision( PRECISION )})`
712
+ );
453
713
 
454
714
  }
455
715
 
@@ -457,65 +717,23 @@ function buildVector2Array( attribute ) {
457
717
 
458
718
  }
459
719
 
460
- function buildPrimvars( attributes ) {
461
-
462
- let string = '';
463
-
464
- for ( let i = 0; i < 4; i ++ ) {
465
-
466
- const id = ( i > 0 ? i : '' );
467
- const attribute = attributes[ 'uv' + id ];
468
-
469
- if ( attribute !== undefined ) {
470
-
471
- string += `
472
- texCoord2f[] primvars:st${ id } = [${ buildVector2Array( attribute )}] (
473
- interpolation = "vertex"
474
- )`;
475
-
476
- }
477
-
478
- }
479
-
480
- // vertex colors
481
-
482
- const colorAttribute = attributes.color;
483
-
484
- if ( colorAttribute !== undefined ) {
485
-
486
- const count = colorAttribute.count;
487
-
488
- string += `
489
- color3f[] primvars:displayColor = [${buildVector3Array( colorAttribute, count )}] (
490
- interpolation = "vertex"
491
- )`;
492
-
493
- }
494
-
495
- return string;
496
-
497
- }
498
-
499
720
  // Materials
500
721
 
501
722
  function buildMaterials( materials, textures, quickLookCompatible = false ) {
502
723
 
503
- const array = [];
724
+ const materialsNode = new USDNode( 'Materials' );
504
725
 
505
726
  for ( const uuid in materials ) {
506
727
 
507
728
  const material = materials[ uuid ];
508
729
 
509
- array.push( buildMaterial( material, textures, quickLookCompatible ) );
730
+ materialsNode.addChild(
731
+ buildMaterial( material, textures, quickLookCompatible )
732
+ );
510
733
 
511
734
  }
512
735
 
513
- return `def "Materials"
514
- {
515
- ${ array.join( '' ) }
516
- }
517
-
518
- `;
736
+ return materialsNode;
519
737
 
520
738
  }
521
739
 
@@ -523,11 +741,9 @@ function buildMaterial( material, textures, quickLookCompatible = false ) {
523
741
 
524
742
  // https://graphics.pixar.com/usd/docs/UsdPreviewSurface-Proposal.html
525
743
 
526
- const pad = ' ';
527
- const inputs = [];
528
- const samplers = [];
744
+ const materialNode = new USDNode( `Material_${material.id}`, 'Material' );
529
745
 
530
- function buildTexture( texture, mapType, color ) {
746
+ function buildTextureNodes( texture, mapType, color ) {
531
747
 
532
748
  const id = texture.source.id + '_' + texture.flipY;
533
749
 
@@ -538,7 +754,7 @@ function buildMaterial( material, textures, quickLookCompatible = false ) {
538
754
  const WRAPPINGS = {
539
755
  1000: 'repeat', // RepeatWrapping
540
756
  1001: 'clamp', // ClampToEdgeWrapping
541
- 1002: 'mirror' // MirroredRepeatWrapping
757
+ 1002: 'mirror', // MirroredRepeatWrapping
542
758
  };
543
759
 
544
760
  const repeat = texture.repeat.clone();
@@ -573,135 +789,248 @@ function buildMaterial( material, textures, quickLookCompatible = false ) {
573
789
 
574
790
  }
575
791
 
576
- return `
577
- def Shader "PrimvarReader_${ mapType }"
578
- {
579
- uniform token info:id = "UsdPrimvarReader_float2"
580
- float2 inputs:fallback = (0.0, 0.0)
581
- token inputs:varname = "${ uv }"
582
- float2 outputs:result
792
+ const primvarReaderNode = new USDNode( `PrimvarReader_${mapType}`, 'Shader' );
793
+ primvarReaderNode.addProperty(
794
+ 'uniform token info:id = "UsdPrimvarReader_float2"'
795
+ );
796
+ primvarReaderNode.addProperty( 'float2 inputs:fallback = (0.0, 0.0)' );
797
+ primvarReaderNode.addProperty( `token inputs:varname = "${uv}"` );
798
+ primvarReaderNode.addProperty( 'float2 outputs:result' );
799
+
800
+ const transform2dNode = new USDNode( `Transform2d_${mapType}`, 'Shader' );
801
+ transform2dNode.addProperty( 'uniform token info:id = "UsdTransform2d"' );
802
+ transform2dNode.addProperty(
803
+ `token inputs:in.connect = </Materials/Material_${material.id}/PrimvarReader_${mapType}.outputs:result>`
804
+ );
805
+ transform2dNode.addProperty(
806
+ `float inputs:rotation = ${( rotation * ( 180 / Math.PI ) ).toFixed(
807
+ PRECISION
808
+ )}`
809
+ );
810
+ transform2dNode.addProperty(
811
+ `float2 inputs:scale = ${buildVector2( repeat )}`
812
+ );
813
+ transform2dNode.addProperty(
814
+ `float2 inputs:translation = ${buildVector2( offset )}`
815
+ );
816
+ transform2dNode.addProperty( 'float2 outputs:result' );
817
+
818
+ const textureNode = new USDNode(
819
+ `Texture_${texture.id}_${mapType}`,
820
+ 'Shader'
821
+ );
822
+ textureNode.addProperty( 'uniform token info:id = "UsdUVTexture"' );
823
+ textureNode.addProperty( `asset inputs:file = @textures/Texture_${id}.png@` );
824
+ textureNode.addProperty(
825
+ `float2 inputs:st.connect = </Materials/Material_${material.id}/Transform2d_${mapType}.outputs:result>`
826
+ );
827
+
828
+ if ( color !== undefined ) {
829
+
830
+ textureNode.addProperty( `float4 inputs:scale = ${buildColor4( color )}` );
831
+
583
832
  }
584
833
 
585
- def Shader "Transform2d_${ mapType }"
586
- {
587
- uniform token info:id = "UsdTransform2d"
588
- token inputs:in.connect = </Materials/Material_${ material.id }/PrimvarReader_${ mapType }.outputs:result>
589
- float inputs:rotation = ${ ( rotation * ( 180 / Math.PI ) ).toFixed( PRECISION ) }
590
- float2 inputs:scale = ${ buildVector2( repeat ) }
591
- float2 inputs:translation = ${ buildVector2( offset ) }
592
- float2 outputs:result
834
+ textureNode.addProperty(
835
+ `token inputs:sourceColorSpace = "${
836
+ texture.colorSpace === NoColorSpace ? 'raw' : 'sRGB'
837
+ }"`
838
+ );
839
+ textureNode.addProperty(
840
+ `token inputs:wrapS = "${WRAPPINGS[ texture.wrapS ]}"`
841
+ );
842
+ textureNode.addProperty(
843
+ `token inputs:wrapT = "${WRAPPINGS[ texture.wrapT ]}"`
844
+ );
845
+ textureNode.addProperty( 'float outputs:r' );
846
+ textureNode.addProperty( 'float outputs:g' );
847
+ textureNode.addProperty( 'float outputs:b' );
848
+ textureNode.addProperty( 'float3 outputs:rgb' );
849
+
850
+ if ( material.transparent || material.alphaTest > 0.0 ) {
851
+
852
+ textureNode.addProperty( 'float outputs:a' );
853
+
593
854
  }
594
855
 
595
- def Shader "Texture_${ texture.id }_${ mapType }"
596
- {
597
- uniform token info:id = "UsdUVTexture"
598
- asset inputs:file = @textures/Texture_${ id }.png@
599
- float2 inputs:st.connect = </Materials/Material_${ material.id }/Transform2d_${ mapType }.outputs:result>
600
- ${ color !== undefined ? 'float4 inputs:scale = ' + buildColor4( color ) : '' }
601
- token inputs:sourceColorSpace = "${ texture.colorSpace === NoColorSpace ? 'raw' : 'sRGB' }"
602
- token inputs:wrapS = "${ WRAPPINGS[ texture.wrapS ] }"
603
- token inputs:wrapT = "${ WRAPPINGS[ texture.wrapT ] }"
604
- float outputs:r
605
- float outputs:g
606
- float outputs:b
607
- float3 outputs:rgb
608
- ${ material.transparent || material.alphaTest > 0.0 ? 'float outputs:a' : '' }
609
- }`;
856
+ return [ primvarReaderNode, transform2dNode, textureNode ];
610
857
 
611
858
  }
612
859
 
613
-
614
860
  if ( material.side === DoubleSide ) {
615
861
 
616
- console.warn( 'THREE.USDZExporter: USDZ does not support double sided materials', material );
862
+ console.warn(
863
+ 'THREE.USDZExporter: USDZ does not support double sided materials',
864
+ material
865
+ );
617
866
 
618
867
  }
619
868
 
869
+ const previewSurfaceNode = new USDNode( 'PreviewSurface', 'Shader' );
870
+ previewSurfaceNode.addProperty( 'uniform token info:id = "UsdPreviewSurface"' );
871
+
620
872
  if ( material.map !== null ) {
621
873
 
622
- inputs.push( `${ pad }color3f inputs:diffuseColor.connect = </Materials/Material_${ material.id }/Texture_${ material.map.id }_diffuse.outputs:rgb>` );
874
+ previewSurfaceNode.addProperty(
875
+ `color3f inputs:diffuseColor.connect = </Materials/Material_${material.id}/Texture_${material.map.id}_diffuse.outputs:rgb>`
876
+ );
623
877
 
624
878
  if ( material.transparent ) {
625
879
 
626
- inputs.push( `${ pad }float inputs:opacity.connect = </Materials/Material_${ material.id }/Texture_${ material.map.id }_diffuse.outputs:a>` );
880
+ previewSurfaceNode.addProperty(
881
+ `float inputs:opacity.connect = </Materials/Material_${material.id}/Texture_${material.map.id}_diffuse.outputs:a>`
882
+ );
627
883
 
628
884
  } else if ( material.alphaTest > 0.0 ) {
629
885
 
630
- inputs.push( `${ pad }float inputs:opacity.connect = </Materials/Material_${ material.id }/Texture_${ material.map.id }_diffuse.outputs:a>` );
631
- inputs.push( `${ pad }float inputs:opacityThreshold = ${material.alphaTest}` );
886
+ previewSurfaceNode.addProperty(
887
+ `float inputs:opacity.connect = </Materials/Material_${material.id}/Texture_${material.map.id}_diffuse.outputs:a>`
888
+ );
889
+ previewSurfaceNode.addProperty(
890
+ `float inputs:opacityThreshold = ${material.alphaTest}`
891
+ );
632
892
 
633
893
  }
634
894
 
635
- samplers.push( buildTexture( material.map, 'diffuse', material.color ) );
895
+ const textureNodes = buildTextureNodes(
896
+ material.map,
897
+ 'diffuse',
898
+ material.color
899
+ );
900
+ textureNodes.forEach( ( node ) => materialNode.addChild( node ) );
636
901
 
637
902
  } else {
638
903
 
639
- inputs.push( `${ pad }color3f inputs:diffuseColor = ${ buildColor( material.color ) }` );
904
+ previewSurfaceNode.addProperty(
905
+ `color3f inputs:diffuseColor = ${buildColor( material.color )}`
906
+ );
640
907
 
641
908
  }
642
909
 
643
910
  if ( material.emissiveMap !== null ) {
644
911
 
645
- inputs.push( `${ pad }color3f inputs:emissiveColor.connect = </Materials/Material_${ material.id }/Texture_${ material.emissiveMap.id }_emissive.outputs:rgb>` );
646
-
647
- samplers.push( buildTexture( material.emissiveMap, 'emissive', new Color( material.emissive.r * material.emissiveIntensity, material.emissive.g * material.emissiveIntensity, material.emissive.b * material.emissiveIntensity ) ) );
912
+ previewSurfaceNode.addProperty(
913
+ `color3f inputs:emissiveColor.connect = </Materials/Material_${material.id}/Texture_${material.emissiveMap.id}_emissive.outputs:rgb>`
914
+ );
915
+
916
+ const emissiveColor = new Color(
917
+ material.emissive.r * material.emissiveIntensity,
918
+ material.emissive.g * material.emissiveIntensity,
919
+ material.emissive.b * material.emissiveIntensity
920
+ );
921
+ const textureNodes = buildTextureNodes(
922
+ material.emissiveMap,
923
+ 'emissive',
924
+ emissiveColor
925
+ );
926
+ textureNodes.forEach( ( node ) => materialNode.addChild( node ) );
648
927
 
649
928
  } else if ( material.emissive.getHex() > 0 ) {
650
929
 
651
- inputs.push( `${ pad }color3f inputs:emissiveColor = ${ buildColor( material.emissive ) }` );
930
+ previewSurfaceNode.addProperty(
931
+ `color3f inputs:emissiveColor = ${buildColor( material.emissive )}`
932
+ );
652
933
 
653
934
  }
654
935
 
655
936
  if ( material.normalMap !== null ) {
656
937
 
657
- inputs.push( `${ pad }normal3f inputs:normal.connect = </Materials/Material_${ material.id }/Texture_${ material.normalMap.id }_normal.outputs:rgb>` );
938
+ previewSurfaceNode.addProperty(
939
+ `normal3f inputs:normal.connect = </Materials/Material_${material.id}/Texture_${material.normalMap.id}_normal.outputs:rgb>`
940
+ );
658
941
 
659
- samplers.push( buildTexture( material.normalMap, 'normal' ) );
942
+ const textureNodes = buildTextureNodes( material.normalMap, 'normal' );
943
+ textureNodes.forEach( ( node ) => materialNode.addChild( node ) );
660
944
 
661
945
  }
662
946
 
663
947
  if ( material.aoMap !== null ) {
664
948
 
665
- inputs.push( `${ pad }float inputs:occlusion.connect = </Materials/Material_${ material.id }/Texture_${ material.aoMap.id }_occlusion.outputs:r>` );
666
-
667
- samplers.push( buildTexture( material.aoMap, 'occlusion', new Color( material.aoMapIntensity, material.aoMapIntensity, material.aoMapIntensity ) ) );
949
+ previewSurfaceNode.addProperty(
950
+ `float inputs:occlusion.connect = </Materials/Material_${material.id}/Texture_${material.aoMap.id}_occlusion.outputs:r>`
951
+ );
952
+
953
+ const aoColor = new Color(
954
+ material.aoMapIntensity,
955
+ material.aoMapIntensity,
956
+ material.aoMapIntensity
957
+ );
958
+ const textureNodes = buildTextureNodes(
959
+ material.aoMap,
960
+ 'occlusion',
961
+ aoColor
962
+ );
963
+ textureNodes.forEach( ( node ) => materialNode.addChild( node ) );
668
964
 
669
965
  }
670
966
 
671
967
  if ( material.roughnessMap !== null ) {
672
968
 
673
- inputs.push( `${ pad }float inputs:roughness.connect = </Materials/Material_${ material.id }/Texture_${ material.roughnessMap.id }_roughness.outputs:g>` );
674
-
675
- samplers.push( buildTexture( material.roughnessMap, 'roughness', new Color( material.roughness, material.roughness, material.roughness ) ) );
969
+ previewSurfaceNode.addProperty(
970
+ `float inputs:roughness.connect = </Materials/Material_${material.id}/Texture_${material.roughnessMap.id}_roughness.outputs:g>`
971
+ );
972
+
973
+ const roughnessColor = new Color(
974
+ material.roughness,
975
+ material.roughness,
976
+ material.roughness
977
+ );
978
+ const textureNodes = buildTextureNodes(
979
+ material.roughnessMap,
980
+ 'roughness',
981
+ roughnessColor
982
+ );
983
+ textureNodes.forEach( ( node ) => materialNode.addChild( node ) );
676
984
 
677
985
  } else {
678
986
 
679
- inputs.push( `${ pad }float inputs:roughness = ${ material.roughness }` );
987
+ previewSurfaceNode.addProperty(
988
+ `float inputs:roughness = ${material.roughness}`
989
+ );
680
990
 
681
991
  }
682
992
 
683
993
  if ( material.metalnessMap !== null ) {
684
994
 
685
- inputs.push( `${ pad }float inputs:metallic.connect = </Materials/Material_${ material.id }/Texture_${ material.metalnessMap.id }_metallic.outputs:b>` );
686
-
687
- samplers.push( buildTexture( material.metalnessMap, 'metallic', new Color( material.metalness, material.metalness, material.metalness ) ) );
995
+ previewSurfaceNode.addProperty(
996
+ `float inputs:metallic.connect = </Materials/Material_${material.id}/Texture_${material.metalnessMap.id}_metallic.outputs:b>`
997
+ );
998
+
999
+ const metalnessColor = new Color(
1000
+ material.metalness,
1001
+ material.metalness,
1002
+ material.metalness
1003
+ );
1004
+ const textureNodes = buildTextureNodes(
1005
+ material.metalnessMap,
1006
+ 'metallic',
1007
+ metalnessColor
1008
+ );
1009
+ textureNodes.forEach( ( node ) => materialNode.addChild( node ) );
688
1010
 
689
1011
  } else {
690
1012
 
691
- inputs.push( `${ pad }float inputs:metallic = ${ material.metalness }` );
1013
+ previewSurfaceNode.addProperty(
1014
+ `float inputs:metallic = ${material.metalness}`
1015
+ );
692
1016
 
693
1017
  }
694
1018
 
695
1019
  if ( material.alphaMap !== null ) {
696
1020
 
697
- inputs.push( `${pad}float inputs:opacity.connect = </Materials/Material_${material.id}/Texture_${material.alphaMap.id}_opacity.outputs:r>` );
698
- inputs.push( `${pad}float inputs:opacityThreshold = 0.0001` );
1021
+ previewSurfaceNode.addProperty(
1022
+ `float inputs:opacity.connect = </Materials/Material_${material.id}/Texture_${material.alphaMap.id}_opacity.outputs:r>`
1023
+ );
1024
+ previewSurfaceNode.addProperty( 'float inputs:opacityThreshold = 0.0001' );
699
1025
 
700
- samplers.push( buildTexture( material.alphaMap, 'opacity' ) );
1026
+ const textureNodes = buildTextureNodes( material.alphaMap, 'opacity' );
1027
+ textureNodes.forEach( ( node ) => materialNode.addChild( node ) );
701
1028
 
702
1029
  } else {
703
1030
 
704
- inputs.push( `${pad}float inputs:opacity = ${material.opacity}` );
1031
+ previewSurfaceNode.addProperty(
1032
+ `float inputs:opacity = ${material.opacity}`
1033
+ );
705
1034
 
706
1035
  }
707
1036
 
@@ -709,115 +1038,164 @@ function buildMaterial( material, textures, quickLookCompatible = false ) {
709
1038
 
710
1039
  if ( material.clearcoatMap !== null ) {
711
1040
 
712
- inputs.push( `${pad}float inputs:clearcoat.connect = </Materials/Material_${material.id}/Texture_${material.clearcoatMap.id}_clearcoat.outputs:r>` );
713
- samplers.push( buildTexture( material.clearcoatMap, 'clearcoat', new Color( material.clearcoat, material.clearcoat, material.clearcoat ) ) );
1041
+ previewSurfaceNode.addProperty(
1042
+ `float inputs:clearcoat.connect = </Materials/Material_${material.id}/Texture_${material.clearcoatMap.id}_clearcoat.outputs:r>`
1043
+ );
1044
+
1045
+ const clearcoatColor = new Color(
1046
+ material.clearcoat,
1047
+ material.clearcoat,
1048
+ material.clearcoat
1049
+ );
1050
+ const textureNodes = buildTextureNodes(
1051
+ material.clearcoatMap,
1052
+ 'clearcoat',
1053
+ clearcoatColor
1054
+ );
1055
+ textureNodes.forEach( ( node ) => materialNode.addChild( node ) );
714
1056
 
715
1057
  } else {
716
1058
 
717
- inputs.push( `${pad}float inputs:clearcoat = ${material.clearcoat}` );
1059
+ previewSurfaceNode.addProperty(
1060
+ `float inputs:clearcoat = ${material.clearcoat}`
1061
+ );
718
1062
 
719
1063
  }
720
1064
 
721
1065
  if ( material.clearcoatRoughnessMap !== null ) {
722
1066
 
723
- inputs.push( `${pad}float inputs:clearcoatRoughness.connect = </Materials/Material_${material.id}/Texture_${material.clearcoatRoughnessMap.id}_clearcoatRoughness.outputs:g>` );
724
- samplers.push( buildTexture( material.clearcoatRoughnessMap, 'clearcoatRoughness', new Color( material.clearcoatRoughness, material.clearcoatRoughness, material.clearcoatRoughness ) ) );
1067
+ previewSurfaceNode.addProperty(
1068
+ `float inputs:clearcoatRoughness.connect = </Materials/Material_${material.id}/Texture_${material.clearcoatRoughnessMap.id}_clearcoatRoughness.outputs:g>`
1069
+ );
1070
+
1071
+ const clearcoatRoughnessColor = new Color(
1072
+ material.clearcoatRoughness,
1073
+ material.clearcoatRoughness,
1074
+ material.clearcoatRoughness
1075
+ );
1076
+ const textureNodes = buildTextureNodes(
1077
+ material.clearcoatRoughnessMap,
1078
+ 'clearcoatRoughness',
1079
+ clearcoatRoughnessColor
1080
+ );
1081
+ textureNodes.forEach( ( node ) => materialNode.addChild( node ) );
725
1082
 
726
1083
  } else {
727
1084
 
728
- inputs.push( `${pad}float inputs:clearcoatRoughness = ${material.clearcoatRoughness}` );
1085
+ previewSurfaceNode.addProperty(
1086
+ `float inputs:clearcoatRoughness = ${material.clearcoatRoughness}`
1087
+ );
729
1088
 
730
1089
  }
731
1090
 
732
- inputs.push( `${ pad }float inputs:ior = ${ material.ior }` );
1091
+ previewSurfaceNode.addProperty( `float inputs:ior = ${material.ior}` );
733
1092
 
734
1093
  }
735
1094
 
736
- return `
737
- def Material "Material_${ material.id }"
738
- {
739
- def Shader "PreviewSurface"
740
- {
741
- uniform token info:id = "UsdPreviewSurface"
742
- ${ inputs.join( '\n' ) }
743
- int inputs:useSpecularWorkflow = 0
744
- token outputs:surface
745
- }
1095
+ previewSurfaceNode.addProperty( 'int inputs:useSpecularWorkflow = 0' );
1096
+ previewSurfaceNode.addProperty( 'token outputs:surface' );
746
1097
 
747
- token outputs:surface.connect = </Materials/Material_${ material.id }/PreviewSurface.outputs:surface>
1098
+ materialNode.addChild( previewSurfaceNode );
748
1099
 
749
- ${ samplers.join( '\n' ) }
1100
+ materialNode.addProperty(
1101
+ `token outputs:surface.connect = </Materials/Material_${material.id}/PreviewSurface.outputs:surface>`
1102
+ );
750
1103
 
751
- }
752
- `;
1104
+ return materialNode;
753
1105
 
754
1106
  }
755
1107
 
756
1108
  function buildColor( color ) {
757
1109
 
758
- return `(${ color.r }, ${ color.g }, ${ color.b })`;
1110
+ return `(${color.r}, ${color.g}, ${color.b})`;
759
1111
 
760
1112
  }
761
1113
 
762
1114
  function buildColor4( color ) {
763
1115
 
764
- return `(${ color.r }, ${ color.g }, ${ color.b }, 1.0)`;
1116
+ return `(${color.r}, ${color.g}, ${color.b}, 1.0)`;
765
1117
 
766
1118
  }
767
1119
 
768
1120
  function buildVector2( vector ) {
769
1121
 
770
- return `(${ vector.x }, ${ vector.y })`;
1122
+ return `(${vector.x}, ${vector.y})`;
771
1123
 
772
1124
  }
773
1125
 
1126
+ function buildCamera( camera, usedNames ) {
774
1127
 
775
- function buildCamera( camera ) {
1128
+ const name = getName( camera, usedNames );
776
1129
 
777
- const name = camera.name ? camera.name : 'Camera_' + camera.id;
1130
+ const transform = buildMatrix( camera.matrix );
778
1131
 
779
- const transform = buildMatrix( camera.matrixWorld );
1132
+ if ( camera.matrix.determinant() < 0 ) {
780
1133
 
781
- if ( camera.matrixWorld.determinant() < 0 ) {
782
-
783
- console.warn( 'THREE.USDZExporter: USDZ does not support negative scales', camera );
1134
+ console.warn(
1135
+ 'THREE.USDZExporter: USDZ does not support negative scales',
1136
+ camera
1137
+ );
784
1138
 
785
1139
  }
786
1140
 
1141
+ const node = new USDNode( name, 'Camera' );
1142
+ node.addProperty( `matrix4d xformOp:transform = ${transform}` );
1143
+ node.addProperty( 'uniform token[] xformOpOrder = ["xformOp:transform"]' );
1144
+
1145
+ const projection = camera.isOrthographicCamera
1146
+ ? 'orthographic'
1147
+ : 'perspective';
1148
+ node.addProperty( `token projection = "${projection}"` );
1149
+
1150
+ const clippingRange = `(${camera.near.toPrecision(
1151
+ PRECISION
1152
+ )}, ${camera.far.toPrecision( PRECISION )})`;
1153
+ node.addProperty( `float2 clippingRange = ${clippingRange}` );
1154
+
1155
+ let horizontalAperture;
787
1156
  if ( camera.isOrthographicCamera ) {
788
1157
 
789
- return `def Camera "${name}"
790
- {
791
- matrix4d xformOp:transform = ${ transform }
792
- uniform token[] xformOpOrder = ["xformOp:transform"]
1158
+ horizontalAperture = (
1159
+ ( Math.abs( camera.left ) + Math.abs( camera.right ) ) *
1160
+ 10
1161
+ ).toPrecision( PRECISION );
793
1162
 
794
- float2 clippingRange = (${ camera.near.toPrecision( PRECISION ) }, ${ camera.far.toPrecision( PRECISION ) })
795
- float horizontalAperture = ${ ( ( Math.abs( camera.left ) + Math.abs( camera.right ) ) * 10 ).toPrecision( PRECISION ) }
796
- float verticalAperture = ${ ( ( Math.abs( camera.top ) + Math.abs( camera.bottom ) ) * 10 ).toPrecision( PRECISION ) }
797
- token projection = "orthographic"
798
- }
1163
+ } else {
1164
+
1165
+ horizontalAperture = camera.getFilmWidth().toPrecision( PRECISION );
1166
+
1167
+ }
1168
+
1169
+ node.addProperty( `float horizontalAperture = ${horizontalAperture}` );
1170
+
1171
+ let verticalAperture;
1172
+ if ( camera.isOrthographicCamera ) {
799
1173
 
800
- `;
1174
+ verticalAperture = (
1175
+ ( Math.abs( camera.top ) + Math.abs( camera.bottom ) ) *
1176
+ 10
1177
+ ).toPrecision( PRECISION );
801
1178
 
802
1179
  } else {
803
1180
 
804
- return `def Camera "${name}"
805
- {
806
- matrix4d xformOp:transform = ${ transform }
807
- uniform token[] xformOpOrder = ["xformOp:transform"]
808
-
809
- float2 clippingRange = (${ camera.near.toPrecision( PRECISION ) }, ${ camera.far.toPrecision( PRECISION ) })
810
- float focalLength = ${ camera.getFocalLength().toPrecision( PRECISION ) }
811
- float focusDistance = ${ camera.focus.toPrecision( PRECISION ) }
812
- float horizontalAperture = ${ camera.getFilmWidth().toPrecision( PRECISION ) }
813
- token projection = "perspective"
814
- float verticalAperture = ${ camera.getFilmHeight().toPrecision( PRECISION ) }
815
- }
1181
+ verticalAperture = camera.getFilmHeight().toPrecision( PRECISION );
1182
+
1183
+ }
1184
+
1185
+ node.addProperty( `float verticalAperture = ${verticalAperture}` );
816
1186
 
817
- `;
1187
+ if ( camera.isPerspectiveCamera ) {
1188
+
1189
+ const focalLength = camera.getFocalLength().toPrecision( PRECISION );
1190
+ node.addProperty( `float focalLength = ${focalLength}` );
1191
+
1192
+ const focusDistance = camera.focus.toPrecision( PRECISION );
1193
+ node.addProperty( `float focusDistance = ${focusDistance}` );
818
1194
 
819
1195
  }
820
1196
 
1197
+ return node;
1198
+
821
1199
  }
822
1200
 
823
1201
  /**
@@ -825,7 +1203,8 @@ function buildCamera( camera ) {
825
1203
  *
826
1204
  * @typedef {Object} USDZExporter~Options
827
1205
  * @property {number} [maxTextureSize=1024] - The maximum texture size that is going to be exported.
828
- * @property {boolean} [includeAnchoringProperties=false] - Whether to include anchoring properties or not.
1206
+ * @property {boolean} [includeAnchoringProperties=true] - Whether to include anchoring properties or not.
1207
+ * @property {boolean} [onlyVisible=true] - Export only visible 3D objects.
829
1208
  * @property {Object} [ar] - If `includeAnchoringProperties` is set to `true`, the anchoring type and alignment
830
1209
  * can be configured via `ar.anchoring.type` and `ar.planeAnchoring.alignment`.
831
1210
  * @property {boolean} [quickLookCompatible=false] - Whether to make the exported USDZ compatible to QuickLook