@needle-tools/three 0.145.2 → 0.146.1

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 (394) hide show
  1. package/README.md +1 -1
  2. package/build/three.cjs +3559 -6924
  3. package/build/three.js +3559 -6924
  4. package/build/three.min.js +1 -2
  5. package/build/three.module.js +732 -339
  6. package/examples/js/animation/AnimationClipCreator.js +0 -8
  7. package/examples/js/animation/CCDIKSolver.js +49 -66
  8. package/examples/js/animation/MMDAnimationHelper.js +66 -137
  9. package/examples/js/animation/MMDPhysics.js +70 -134
  10. package/examples/js/cameras/CinematicCamera.js +33 -22
  11. package/examples/js/controls/ArcballControls.js +138 -405
  12. package/examples/js/controls/DragControls.js +8 -33
  13. package/examples/js/controls/FirstPersonControls.js +32 -54
  14. package/examples/js/controls/FlyControls.js +29 -55
  15. package/examples/js/controls/OrbitControls.js +85 -95
  16. package/examples/js/controls/PointerLockControls.js +5 -14
  17. package/examples/js/controls/TrackballControls.js +33 -86
  18. package/examples/js/controls/TransformControls.js +84 -169
  19. package/examples/js/csm/CSM.js +4 -39
  20. package/examples/js/csm/CSMFrustum.js +3 -9
  21. package/examples/js/csm/CSMHelper.js +24 -4
  22. package/examples/js/csm/CSMShader.js +2 -6
  23. package/examples/js/curves/CurveExtras.js +27 -27
  24. package/examples/js/curves/NURBSCurve.js +4 -16
  25. package/examples/js/curves/NURBSSurface.js +3 -9
  26. package/examples/js/curves/NURBSUtils.js +8 -45
  27. package/examples/js/effects/AnaglyphEffect.js +4 -18
  28. package/examples/js/effects/AsciiEffect.js +32 -31
  29. package/examples/js/effects/OutlineEffect.js +26 -30
  30. package/examples/js/effects/ParallaxBarrierEffect.js +0 -13
  31. package/examples/js/effects/PeppersGhostEffect.js +12 -39
  32. package/examples/js/effects/StereoEffect.js +0 -4
  33. package/examples/js/environments/RoomEnvironment.js +12 -10
  34. package/examples/js/exporters/ColladaExporter.js +48 -65
  35. package/examples/js/exporters/DRACOExporter.js +22 -22
  36. package/examples/js/exporters/EXRExporter.js +15 -18
  37. package/examples/js/exporters/GLTFExporter.js +143 -261
  38. package/examples/js/exporters/MMDExporter.js +5 -12
  39. package/examples/js/exporters/OBJExporter.js +42 -33
  40. package/examples/js/exporters/PLYExporter.js +38 -33
  41. package/examples/js/exporters/STLExporter.js +5 -7
  42. package/examples/js/exporters/USDZExporter.js +110 -25
  43. package/examples/js/geometries/BoxLineGeometry.js +0 -1
  44. package/examples/js/geometries/ConvexGeometry.js +11 -6
  45. package/examples/js/geometries/DecalGeometry.js +53 -20
  46. package/examples/js/geometries/LightningStrike.js +54 -67
  47. package/examples/js/geometries/ParametricGeometries.js +8 -7
  48. package/examples/js/geometries/ParametricGeometry.js +25 -12
  49. package/examples/js/geometries/RoundedBoxGeometry.js +21 -19
  50. package/examples/js/geometries/TeapotGeometry.js +54 -50
  51. package/examples/js/geometries/TextGeometry.js +6 -4
  52. package/examples/js/helpers/LightProbeHelper.js +1 -2
  53. package/examples/js/helpers/OctreeHelper.js +22 -20
  54. package/examples/js/helpers/PositionalAudioHelper.js +8 -6
  55. package/examples/js/helpers/RectAreaLightHelper.js +6 -7
  56. package/examples/js/helpers/VertexNormalsHelper.js +15 -13
  57. package/examples/js/helpers/VertexTangentsHelper.js +15 -9
  58. package/examples/js/helpers/ViewHelper.js +31 -16
  59. package/examples/js/interactive/HTMLMesh.js +22 -33
  60. package/examples/js/interactive/InteractiveGroup.js +6 -12
  61. package/examples/js/interactive/SelectionBox.js +3 -70
  62. package/examples/js/interactive/SelectionHelper.js +0 -8
  63. package/examples/js/lights/LightProbeGenerator.js +32 -39
  64. package/examples/js/lights/RectAreaLightUniformsLib.js +5 -1
  65. package/examples/js/lines/LineGeometry.js +3 -5
  66. package/examples/js/lines/LineMaterial.js +4 -11
  67. package/examples/js/lines/LineSegments2.js +38 -89
  68. package/examples/js/lines/LineSegmentsGeometry.js +7 -28
  69. package/examples/js/lines/Wireframe.js +2 -7
  70. package/examples/js/lines/WireframeGeometry2.js +3 -1
  71. package/examples/js/loaders/3DMLoader.js +58 -155
  72. package/examples/js/loaders/3MFLoader.js +72 -106
  73. package/examples/js/loaders/AMFLoader.js +0 -25
  74. package/examples/js/loaders/BVHLoader.js +44 -43
  75. package/examples/js/loaders/BasisTextureLoader.js +16 -46
  76. package/examples/js/loaders/ColladaLoader.js +201 -359
  77. package/examples/js/loaders/DDSLoader.js +24 -25
  78. package/examples/js/loaders/DRACOLoader.js +29 -66
  79. package/examples/js/loaders/EXRLoader.js +67 -164
  80. package/examples/js/loaders/FBXLoader.js +286 -441
  81. package/examples/js/loaders/FontLoader.js +6 -15
  82. package/examples/js/loaders/GCodeLoader.js +15 -16
  83. package/examples/js/loaders/GLTFLoader.js +354 -405
  84. package/examples/js/loaders/HDRCubeTextureLoader.js +0 -6
  85. package/examples/js/loaders/KMZLoader.js +3 -7
  86. package/examples/js/loaders/KTXLoader.js +12 -30
  87. package/examples/js/loaders/LDrawLoader.js +178 -289
  88. package/examples/js/loaders/LUT3dlLoader.js +7 -11
  89. package/examples/js/loaders/LUTCubeLoader.js +0 -8
  90. package/examples/js/loaders/LWOLoader.js +59 -124
  91. package/examples/js/loaders/LogLuvLoader.js +27 -77
  92. package/examples/js/loaders/LottieLoader.js +4 -4
  93. package/examples/js/loaders/MD2Loader.js +26 -27
  94. package/examples/js/loaders/MDDLoader.js +6 -10
  95. package/examples/js/loaders/MMDLoader.js +180 -189
  96. package/examples/js/loaders/MTLLoader.js +18 -47
  97. package/examples/js/loaders/MaterialXLoader.js +392 -0
  98. package/examples/js/loaders/NRRDLoader.js +44 -84
  99. package/examples/js/loaders/OBJLoader.js +50 -65
  100. package/examples/js/loaders/PCDLoader.js +34 -29
  101. package/examples/js/loaders/PDBLoader.js +17 -13
  102. package/examples/js/loaders/PLYLoader.js +9 -39
  103. package/examples/js/loaders/PRWMLoader.js +11 -22
  104. package/examples/js/loaders/PVRLoader.js +7 -16
  105. package/examples/js/loaders/RGBELoader.js +36 -61
  106. package/examples/js/loaders/RGBMLoader.js +26 -87
  107. package/examples/js/loaders/STLLoader.js +20 -27
  108. package/examples/js/loaders/SVGLoader.js +361 -233
  109. package/examples/js/loaders/TDSLoader.js +81 -118
  110. package/examples/js/loaders/TGALoader.js +39 -41
  111. package/examples/js/loaders/TIFFLoader.js +0 -1
  112. package/examples/js/loaders/TTFLoader.js +0 -8
  113. package/examples/js/loaders/TiltLoader.js +14 -15
  114. package/examples/js/loaders/VOXLoader.js +8 -16
  115. package/examples/js/loaders/VRMLLoader.js +243 -340
  116. package/examples/js/loaders/VTKLoader.js +101 -118
  117. package/examples/js/loaders/XYZLoader.js +2 -4
  118. package/examples/js/loaders/lwo/IFFParser.js +55 -136
  119. package/examples/js/loaders/lwo/LWO2Parser.js +32 -83
  120. package/examples/js/loaders/lwo/LWO3Parser.js +31 -73
  121. package/examples/js/materials/MeshGouraudMaterial.js +15 -13
  122. package/examples/js/math/Capsule.js +0 -17
  123. package/examples/js/math/ColorConverter.js +3 -3
  124. package/examples/js/math/ConvexHull.js +183 -139
  125. package/examples/js/math/ImprovedNoise.js +1 -1
  126. package/examples/js/math/Lut.js +8 -15
  127. package/examples/js/math/MeshSurfaceSampler.js +6 -28
  128. package/examples/js/math/OBB.js +90 -49
  129. package/examples/js/math/Octree.js +2 -57
  130. package/examples/js/math/SimplexNoise.js +74 -88
  131. package/examples/js/misc/ConvexObjectBreaker.js +37 -48
  132. package/examples/js/misc/GPUComputationRenderer.js +14 -18
  133. package/examples/js/misc/Gyroscope.js +5 -9
  134. package/examples/js/misc/MD2Character.js +14 -23
  135. package/examples/js/misc/MD2CharacterComplex.js +73 -54
  136. package/examples/js/misc/MorphAnimMesh.js +0 -6
  137. package/examples/js/misc/MorphBlendMesh.js +3 -30
  138. package/examples/js/misc/ProgressiveLightMap.js +47 -43
  139. package/examples/js/misc/RollerCoaster.js +17 -24
  140. package/examples/js/misc/TubePainter.js +18 -12
  141. package/examples/js/misc/Volume.js +16 -45
  142. package/examples/js/misc/VolumeSlice.js +14 -24
  143. package/examples/js/modifiers/CurveModifier.js +19 -21
  144. package/examples/js/modifiers/EdgeSplitModifier.js +0 -30
  145. package/examples/js/modifiers/SimplifyModifier.js +56 -59
  146. package/examples/js/modifiers/TessellateModifier.js +2 -9
  147. package/examples/js/objects/GroundProjectedEnv.js +2 -14
  148. package/examples/js/objects/Lensflare.js +47 -38
  149. package/examples/js/objects/LightningStorm.js +10 -13
  150. package/examples/js/objects/MarchingCubes.js +80 -59
  151. package/examples/js/objects/Reflector.js +22 -20
  152. package/examples/js/objects/ReflectorForSSRPass.js +19 -23
  153. package/examples/js/objects/Refractor.js +52 -30
  154. package/examples/js/objects/ShadowMesh.js +1 -2
  155. package/examples/js/objects/Sky.js +2 -7
  156. package/examples/js/objects/Water.js +23 -18
  157. package/examples/js/objects/Water2.js +20 -19
  158. package/examples/js/physics/AmmoPhysics.js +23 -20
  159. package/examples/js/physics/OimoPhysics.js +19 -17
  160. package/examples/js/postprocessing/AdaptiveToneMappingPass.js +13 -20
  161. package/examples/js/postprocessing/AfterimagePass.js +19 -12
  162. package/examples/js/postprocessing/BloomPass.js +38 -17
  163. package/examples/js/postprocessing/BokehPass.js +29 -12
  164. package/examples/js/postprocessing/ClearPass.js +1 -6
  165. package/examples/js/postprocessing/CubeTexturePass.js +12 -9
  166. package/examples/js/postprocessing/DotScreenPass.js +7 -5
  167. package/examples/js/postprocessing/EffectComposer.js +25 -32
  168. package/examples/js/postprocessing/FilmPass.js +7 -5
  169. package/examples/js/postprocessing/GlitchPass.js +10 -11
  170. package/examples/js/postprocessing/HalftonePass.js +9 -9
  171. package/examples/js/postprocessing/LUTPass.js +2 -15
  172. package/examples/js/postprocessing/MaskPass.js +20 -17
  173. package/examples/js/postprocessing/OutlinePass.js +45 -36
  174. package/examples/js/postprocessing/Pass.js +11 -14
  175. package/examples/js/postprocessing/RenderPass.js +3 -7
  176. package/examples/js/postprocessing/SAOPass.js +40 -32
  177. package/examples/js/postprocessing/SMAAPass.js +34 -17
  178. package/examples/js/postprocessing/SSAARenderPass.js +14 -14
  179. package/examples/js/postprocessing/SSAOPass.js +56 -42
  180. package/examples/js/postprocessing/SSRPass.js +78 -61
  181. package/examples/js/postprocessing/SavePass.js +14 -6
  182. package/examples/js/postprocessing/ShaderPass.js +9 -8
  183. package/examples/js/postprocessing/TAARenderPass.js +11 -9
  184. package/examples/js/postprocessing/TexturePass.js +7 -4
  185. package/examples/js/postprocessing/UnrealBloomPass.js +43 -25
  186. package/examples/js/renderers/CSS2DRenderer.js +2 -21
  187. package/examples/js/renderers/CSS3DRenderer.js +3 -24
  188. package/examples/js/renderers/Projector.js +29 -85
  189. package/examples/js/renderers/SVGRenderer.js +4 -50
  190. package/examples/js/shaders/ACESFilmicToneMappingShader.js +3 -6
  191. package/examples/js/shaders/AfterimageShader.js +3 -6
  192. package/examples/js/shaders/BasicShader.js +3 -6
  193. package/examples/js/shaders/BleachBypassShader.js +3 -6
  194. package/examples/js/shaders/BlendShader.js +3 -6
  195. package/examples/js/shaders/BokehShader.js +3 -6
  196. package/examples/js/shaders/BokehShader2.js +4 -13
  197. package/examples/js/shaders/BrightnessContrastShader.js +3 -6
  198. package/examples/js/shaders/ColorCorrectionShader.js +2 -6
  199. package/examples/js/shaders/ColorifyShader.js +2 -6
  200. package/examples/js/shaders/ConvolutionShader.js +5 -10
  201. package/examples/js/shaders/CopyShader.js +3 -6
  202. package/examples/js/shaders/DOFMipMapShader.js +3 -6
  203. package/examples/js/shaders/DepthLimitedBlurShader.js +2 -9
  204. package/examples/js/shaders/DigitalGlitch.js +3 -6
  205. package/examples/js/shaders/DotScreenShader.js +2 -6
  206. package/examples/js/shaders/FXAAShader.js +1 -3
  207. package/examples/js/shaders/FilmShader.js +3 -6
  208. package/examples/js/shaders/FocusShader.js +3 -6
  209. package/examples/js/shaders/FreiChenShader.js +2 -6
  210. package/examples/js/shaders/GammaCorrectionShader.js +3 -6
  211. package/examples/js/shaders/GodRaysShader.js +11 -24
  212. package/examples/js/shaders/HalftoneShader.js +3 -6
  213. package/examples/js/shaders/HorizontalBlurShader.js +3 -6
  214. package/examples/js/shaders/HorizontalTiltShiftShader.js +3 -6
  215. package/examples/js/shaders/HueSaturationShader.js +3 -6
  216. package/examples/js/shaders/KaleidoShader.js +3 -6
  217. package/examples/js/shaders/LuminosityHighPassShader.js +2 -6
  218. package/examples/js/shaders/LuminosityShader.js +3 -6
  219. package/examples/js/shaders/MMDToonShader.js +2 -6
  220. package/examples/js/shaders/MirrorShader.js +3 -6
  221. package/examples/js/shaders/NormalMapShader.js +2 -6
  222. package/examples/js/shaders/RGBShiftShader.js +3 -6
  223. package/examples/js/shaders/SAOShader.js +2 -6
  224. package/examples/js/shaders/SMAAShader.js +6 -18
  225. package/examples/js/shaders/SSAOShader.js +2 -6
  226. package/examples/js/shaders/SSRShader.js +6 -18
  227. package/examples/js/shaders/SepiaShader.js +3 -6
  228. package/examples/js/shaders/SobelOperatorShader.js +2 -6
  229. package/examples/js/shaders/TechnicolorShader.js +3 -6
  230. package/examples/js/shaders/ToneMapShader.js +3 -6
  231. package/examples/js/shaders/ToonShader.js +8 -24
  232. package/examples/js/shaders/TriangleBlurShader.js +2 -6
  233. package/examples/js/shaders/UnpackDepthRGBAShader.js +3 -6
  234. package/examples/js/shaders/VelocityShader.js +126 -0
  235. package/examples/js/shaders/VerticalBlurShader.js +3 -6
  236. package/examples/js/shaders/VerticalTiltShiftShader.js +3 -6
  237. package/examples/js/shaders/VignetteShader.js +3 -6
  238. package/examples/js/shaders/VolumeShader.js +2 -6
  239. package/examples/js/shaders/WaterRefractionShader.js +2 -6
  240. package/examples/js/textures/FlakesTexture.js +0 -1
  241. package/examples/js/utils/BufferGeometryUtils.js +234 -168
  242. package/examples/js/utils/CameraUtils.js +5 -20
  243. package/examples/js/utils/GPUStatsPanel.js +3 -12
  244. package/examples/js/utils/GeometryCompressionUtils.js +19 -44
  245. package/examples/js/utils/GeometryUtils.js +13 -18
  246. package/examples/js/utils/LDrawUtils.js +8 -11
  247. package/examples/js/utils/PackedPhongMaterial.js +6 -4
  248. package/examples/js/utils/SceneUtils.js +117 -6
  249. package/examples/js/utils/ShadowMapViewer.js +17 -14
  250. package/examples/js/utils/SkeletonUtils.js +13 -27
  251. package/examples/js/utils/UVsDebug.js +20 -12
  252. package/examples/js/utils/WorkerPool.js +1 -11
  253. package/examples/jsm/animation/CCDIKSolver.js +1 -1
  254. package/examples/jsm/capabilities/WebGPU.js +3 -1
  255. package/examples/jsm/controls/OrbitControls.js +44 -4
  256. package/examples/jsm/exporters/GLTFExporter.js +17 -131
  257. package/examples/jsm/exporters/USDZExporter.js +94 -28
  258. package/examples/jsm/interactive/HTMLMesh.js +2 -0
  259. package/examples/jsm/libs/lottie_canvas.module.js +14844 -0
  260. package/examples/jsm/loaders/3DMLoader.js +1 -2
  261. package/examples/jsm/loaders/ColladaLoader.js +28 -0
  262. package/examples/jsm/loaders/FBXLoader.js +16 -2
  263. package/examples/jsm/loaders/GLTFLoader.js +204 -377
  264. package/examples/jsm/loaders/KTX2Loader.js +68 -29
  265. package/examples/jsm/loaders/LDrawLoader.js +14 -13
  266. package/examples/jsm/loaders/LottieLoader.js +4 -2
  267. package/examples/jsm/loaders/MaterialXLoader.js +728 -0
  268. package/examples/jsm/loaders/PCDLoader.js +1 -1
  269. package/examples/jsm/loaders/PLYLoader.js +68 -16
  270. package/examples/jsm/loaders/SVGLoader.js +227 -14
  271. package/examples/jsm/loaders/USDZLoader.js +31 -16
  272. package/examples/jsm/nodes/Nodes.js +14 -2
  273. package/examples/jsm/nodes/accessors/Object3DNode.js +1 -1
  274. package/examples/jsm/nodes/accessors/PositionNode.js +6 -0
  275. package/examples/jsm/nodes/accessors/ReferenceNode.js +1 -1
  276. package/examples/jsm/nodes/accessors/SkinningNode.js +1 -1
  277. package/examples/jsm/nodes/core/Node.js +1 -1
  278. package/examples/jsm/nodes/core/NodeBuilder.js +36 -4
  279. package/examples/jsm/nodes/core/NodeFrame.js +2 -2
  280. package/examples/jsm/nodes/core/NodeVarying.js +7 -4
  281. package/examples/jsm/nodes/core/VaryingNode.js +6 -4
  282. package/examples/jsm/nodes/core/constants.js +13 -13
  283. package/examples/jsm/nodes/display/PosterizeNode.js +25 -0
  284. package/examples/jsm/nodes/display/ViewportNode.js +106 -0
  285. package/examples/jsm/nodes/gpgpu/ComputeNode.js +1 -1
  286. package/examples/jsm/nodes/lighting/AnalyticLightNode.js +1 -1
  287. package/examples/jsm/nodes/loaders/NodeMaterialLoader.js +3 -1
  288. package/examples/jsm/nodes/materials/Materials.js +9 -7
  289. package/examples/jsm/nodes/materials/NodeMaterial.js +9 -1
  290. package/examples/jsm/nodes/materialx/MaterialXNodes.js +6 -2
  291. package/examples/jsm/nodes/materialx/lib/mx_transform_color.js +18 -0
  292. package/examples/jsm/nodes/math/MathNode.js +5 -0
  293. package/examples/jsm/nodes/math/OperatorNode.js +6 -1
  294. package/examples/jsm/nodes/shadernode/ShaderNode.js +26 -13
  295. package/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js +2 -0
  296. package/examples/jsm/nodes/shadernode/ShaderNodeElements.js +18 -0
  297. package/examples/jsm/nodes/utils/EquirectUVNode.js +27 -0
  298. package/examples/jsm/nodes/utils/JoinNode.js +8 -2
  299. package/examples/jsm/nodes/utils/MatcapUVNode.js +2 -4
  300. package/examples/jsm/nodes/utils/MaxMipLevelNode.js +1 -1
  301. package/examples/jsm/nodes/utils/SpriteSheetUVNode.js +8 -10
  302. package/examples/jsm/nodes/utils/TimerNode.js +1 -1
  303. package/examples/jsm/nodes/utils/TriplanarTexturesNode.js +51 -0
  304. package/examples/jsm/postprocessing/AfterimagePass.js +17 -4
  305. package/examples/jsm/postprocessing/BloomPass.js +22 -3
  306. package/examples/jsm/postprocessing/BokehPass.js +18 -4
  307. package/examples/jsm/postprocessing/CubeTexturePass.js +12 -5
  308. package/examples/jsm/postprocessing/DotScreenPass.js +8 -0
  309. package/examples/jsm/postprocessing/EffectComposer.js +9 -0
  310. package/examples/jsm/postprocessing/FilmPass.js +8 -0
  311. package/examples/jsm/postprocessing/GlitchPass.js +13 -1
  312. package/examples/jsm/postprocessing/HalftonePass.js +8 -0
  313. package/examples/jsm/postprocessing/OutlinePass.js +10 -0
  314. package/examples/jsm/postprocessing/Pass.js +2 -0
  315. package/examples/jsm/postprocessing/RenderPixelatedPass.js +234 -0
  316. package/examples/jsm/postprocessing/SAOPass.js +20 -0
  317. package/examples/jsm/postprocessing/SMAAPass.js +16 -0
  318. package/examples/jsm/postprocessing/SSAARenderPass.js +4 -0
  319. package/examples/jsm/postprocessing/SavePass.js +17 -1
  320. package/examples/jsm/postprocessing/ShaderPass.js +8 -0
  321. package/examples/jsm/postprocessing/TAARenderPass.js +9 -0
  322. package/examples/jsm/postprocessing/TexturePass.js +8 -0
  323. package/examples/jsm/postprocessing/UnrealBloomPass.js +16 -0
  324. package/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js +39 -16
  325. package/examples/jsm/renderers/webgpu/WebGPUAnimation.js +58 -0
  326. package/examples/jsm/renderers/webgpu/WebGPUAttributes.js +63 -5
  327. package/examples/jsm/renderers/webgpu/WebGPUBackground.js +36 -7
  328. package/examples/jsm/renderers/webgpu/WebGPURenderer.js +47 -12
  329. package/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js +35 -5
  330. package/examples/jsm/shaders/MMDToonShader.js +0 -2
  331. package/examples/jsm/shaders/VelocityShader.js +128 -0
  332. package/examples/jsm/utils/BufferGeometryUtils.js +130 -6
  333. package/examples/jsm/utils/SceneUtils.js +129 -4
  334. package/examples/jsm/utils/TextureUtils.js +85 -0
  335. package/examples/jsm/webxr/OculusHandModel.js +1 -1
  336. package/examples/jsm/webxr/XRHandMeshModel.js +6 -3
  337. package/package.json +11 -12
  338. package/src/Three.js +1 -0
  339. package/src/audio/AudioContext.js +5 -5
  340. package/src/cameras/CubeCamera.js +14 -14
  341. package/src/constants.js +1 -1
  342. package/src/core/InstancedBufferGeometry.js +1 -7
  343. package/src/extras/Earcut.js +67 -67
  344. package/src/helpers/DirectionalLightHelper.js +5 -1
  345. package/src/helpers/HemisphereLightHelper.js +4 -1
  346. package/src/helpers/PointLightHelper.js +2 -1
  347. package/src/helpers/SpotLightHelper.js +4 -2
  348. package/src/lights/PointLight.js +2 -2
  349. package/src/lights/SpotLight.js +2 -2
  350. package/src/loaders/FileLoader.js +4 -1
  351. package/src/loaders/ObjectLoader.js +5 -1
  352. package/src/materials/Material.js +1 -1
  353. package/src/math/Color.js +5 -5
  354. package/src/math/Matrix3.js +53 -18
  355. package/src/math/Ray.js +2 -5
  356. package/src/math/Sphere.js +19 -26
  357. package/src/objects/InstancedMesh.js +7 -0
  358. package/src/objects/LOD.js +25 -6
  359. package/src/renderers/WebGL3DRenderTarget.js +1 -1
  360. package/src/renderers/WebGLArrayRenderTarget.js +1 -1
  361. package/src/renderers/WebGLCubeRenderTarget.js +1 -1
  362. package/src/renderers/WebGLMultipleRenderTargets.js +1 -1
  363. package/src/renderers/WebGLRenderTarget.js +1 -1
  364. package/src/renderers/WebGLRenderer.js +36 -62
  365. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +0 -4
  366. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +0 -1
  367. package/src/renderers/shaders/ShaderChunk/lights_lambert_pars_fragment.glsl.js +0 -2
  368. package/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl.js +0 -2
  369. package/src/renderers/shaders/ShaderChunk/lights_toon_pars_fragment.glsl.js +0 -2
  370. package/src/renderers/shaders/ShaderChunk/packing.glsl.js +8 -0
  371. package/src/renderers/shaders/ShaderChunk.js +3 -0
  372. package/src/renderers/shaders/ShaderLib/background.glsl.js +7 -2
  373. package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +62 -0
  374. package/src/renderers/shaders/ShaderLib/cube.glsl.js +4 -6
  375. package/src/renderers/shaders/ShaderLib.js +20 -6
  376. package/src/renderers/shaders/UniformsLib.js +1 -1
  377. package/src/renderers/shaders/UniformsUtils.js +15 -0
  378. package/src/renderers/webgl/WebGLAttributes.js +2 -0
  379. package/src/renderers/webgl/WebGLBackground.js +15 -7
  380. package/src/renderers/webgl/WebGLCubeUVMaps.js +1 -1
  381. package/src/renderers/webgl/WebGLLights.js +0 -4
  382. package/src/renderers/webgl/WebGLMaterials.js +2 -1
  383. package/src/renderers/webgl/WebGLShadowMap.js +3 -1
  384. package/src/renderers/webgl/WebGLState.js +31 -1
  385. package/src/renderers/webgl/WebGLTextures.js +71 -18
  386. package/src/renderers/webgl/WebGLUniforms.js +116 -20
  387. package/src/renderers/webgl/WebGLUtils.js +1 -1
  388. package/src/renderers/webxr/WebXRController.js +46 -13
  389. package/src/renderers/webxr/WebXRManager.js +85 -3
  390. package/src/scenes/Scene.js +8 -0
  391. package/src/textures/CompressedArrayTexture.js +18 -0
  392. package/examples/js/libs/lottie_canvas.js +0 -12751
  393. package/examples/js/shaders/PixelShader.js +0 -51
  394. package/examples/jsm/shaders/PixelShader.js +0 -44
@@ -4,14 +4,15 @@
4
4
 
5
5
  constructor( manager ) {
6
6
 
7
- super( manager ); // Default dots per inch
7
+ super( manager );
8
8
 
9
- this.defaultDPI = 90; // Accepted units: 'mm', 'cm', 'in', 'pt', 'pc', 'px'
9
+ // Default dots per inch
10
+ this.defaultDPI = 90;
10
11
 
12
+ // Accepted units: 'mm', 'cm', 'in', 'pt', 'pc', 'px'
11
13
  this.defaultUnit = 'px';
12
14
 
13
15
  }
14
-
15
16
  load( url, onLoad, onProgress, onError ) {
16
17
 
17
18
  const scope = this;
@@ -44,77 +45,62 @@
44
45
  }, onProgress, onError );
45
46
 
46
47
  }
47
-
48
48
  parse( text ) {
49
49
 
50
50
  const scope = this;
51
-
52
51
  function parseNode( node, style ) {
53
52
 
54
53
  if ( node.nodeType !== 1 ) return;
55
54
  const transform = getNodeTransform( node );
56
55
  let isDefsNode = false;
57
56
  let path = null;
58
-
59
57
  switch ( node.nodeName ) {
60
58
 
61
59
  case 'svg':
62
60
  style = parseStyle( node, style );
63
61
  break;
64
-
65
62
  case 'style':
66
63
  parseCSSStylesheet( node );
67
64
  break;
68
-
69
65
  case 'g':
70
66
  style = parseStyle( node, style );
71
67
  break;
72
-
73
68
  case 'path':
74
69
  style = parseStyle( node, style );
75
70
  if ( node.hasAttribute( 'd' ) ) path = parsePathNode( node );
76
71
  break;
77
-
78
72
  case 'rect':
79
73
  style = parseStyle( node, style );
80
74
  path = parseRectNode( node );
81
75
  break;
82
-
83
76
  case 'polygon':
84
77
  style = parseStyle( node, style );
85
78
  path = parsePolygonNode( node );
86
79
  break;
87
-
88
80
  case 'polyline':
89
81
  style = parseStyle( node, style );
90
82
  path = parsePolylineNode( node );
91
83
  break;
92
-
93
84
  case 'circle':
94
85
  style = parseStyle( node, style );
95
86
  path = parseCircleNode( node );
96
87
  break;
97
-
98
88
  case 'ellipse':
99
89
  style = parseStyle( node, style );
100
90
  path = parseEllipseNode( node );
101
91
  break;
102
-
103
92
  case 'line':
104
93
  style = parseStyle( node, style );
105
94
  path = parseLineNode( node );
106
95
  break;
107
-
108
96
  case 'defs':
109
97
  isDefsNode = true;
110
98
  break;
111
-
112
99
  case 'use':
113
100
  style = parseStyle( node, style );
114
101
  const href = node.getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ) || '';
115
102
  const usedNodeId = href.substring( 1 );
116
103
  const usedNode = node.viewportElement.getElementById( usedNodeId );
117
-
118
104
  if ( usedNode ) {
119
105
 
120
106
  parseNode( usedNode, style );
@@ -126,8 +112,8 @@
126
112
  }
127
113
 
128
114
  break;
129
-
130
- default: // console.log( node );
115
+ default:
116
+ // console.log( node );
131
117
 
132
118
  }
133
119
 
@@ -149,11 +135,9 @@
149
135
  }
150
136
 
151
137
  const childNodes = node.childNodes;
152
-
153
138
  for ( let i = 0; i < childNodes.length; i ++ ) {
154
139
 
155
140
  const node = childNodes[ i ];
156
-
157
141
  if ( isDefsNode && node.nodeName !== 'style' && node.nodeName !== 'defs' ) {
158
142
 
159
143
  // Ignore everything in defs except CSS style definitions
@@ -170,7 +154,6 @@
170
154
  if ( transform ) {
171
155
 
172
156
  transformStack.pop();
173
-
174
157
  if ( transformStack.length > 0 ) {
175
158
 
176
159
  currentTransform.copy( transformStack[ transformStack.length - 1 ] );
@@ -193,16 +176,16 @@
193
176
  const firstPoint = new THREE.Vector2();
194
177
  let isFirstPoint = true;
195
178
  let doSetFirstPoint = false;
196
- const d = node.getAttribute( 'd' ); // console.log( d );
179
+ const d = node.getAttribute( 'd' );
197
180
 
198
- const commands = d.match( /[a-df-z][^a-df-z]*/ig );
181
+ // console.log( d );
199
182
 
183
+ const commands = d.match( /[a-df-z][^a-df-z]*/ig );
200
184
  for ( let i = 0, l = commands.length; i < l; i ++ ) {
201
185
 
202
186
  const command = commands[ i ];
203
187
  const type = command.charAt( 0 );
204
188
  const data = command.slice( 1 ).trim();
205
-
206
189
  if ( isFirstPoint === true ) {
207
190
 
208
191
  doSetFirstPoint = true;
@@ -211,19 +194,16 @@
211
194
  }
212
195
 
213
196
  let numbers;
214
-
215
197
  switch ( type ) {
216
198
 
217
199
  case 'M':
218
200
  numbers = parseFloats( data );
219
-
220
201
  for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) {
221
202
 
222
203
  point.x = numbers[ j + 0 ];
223
204
  point.y = numbers[ j + 1 ];
224
205
  control.x = point.x;
225
206
  control.y = point.y;
226
-
227
207
  if ( j === 0 ) {
228
208
 
229
209
  path.moveTo( point.x, point.y );
@@ -239,10 +219,8 @@
239
219
  }
240
220
 
241
221
  break;
242
-
243
222
  case 'H':
244
223
  numbers = parseFloats( data );
245
-
246
224
  for ( let j = 0, jl = numbers.length; j < jl; j ++ ) {
247
225
 
248
226
  point.x = numbers[ j ];
@@ -254,10 +232,8 @@
254
232
  }
255
233
 
256
234
  break;
257
-
258
235
  case 'V':
259
236
  numbers = parseFloats( data );
260
-
261
237
  for ( let j = 0, jl = numbers.length; j < jl; j ++ ) {
262
238
 
263
239
  point.y = numbers[ j ];
@@ -269,10 +245,8 @@
269
245
  }
270
246
 
271
247
  break;
272
-
273
248
  case 'L':
274
249
  numbers = parseFloats( data );
275
-
276
250
  for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) {
277
251
 
278
252
  point.x = numbers[ j + 0 ];
@@ -285,10 +259,8 @@
285
259
  }
286
260
 
287
261
  break;
288
-
289
262
  case 'C':
290
263
  numbers = parseFloats( data );
291
-
292
264
  for ( let j = 0, jl = numbers.length; j < jl; j += 6 ) {
293
265
 
294
266
  path.bezierCurveTo( numbers[ j + 0 ], numbers[ j + 1 ], numbers[ j + 2 ], numbers[ j + 3 ], numbers[ j + 4 ], numbers[ j + 5 ] );
@@ -301,10 +273,8 @@
301
273
  }
302
274
 
303
275
  break;
304
-
305
276
  case 'S':
306
277
  numbers = parseFloats( data );
307
-
308
278
  for ( let j = 0, jl = numbers.length; j < jl; j += 4 ) {
309
279
 
310
280
  path.bezierCurveTo( getReflection( point.x, control.x ), getReflection( point.y, control.y ), numbers[ j + 0 ], numbers[ j + 1 ], numbers[ j + 2 ], numbers[ j + 3 ] );
@@ -317,10 +287,8 @@
317
287
  }
318
288
 
319
289
  break;
320
-
321
290
  case 'Q':
322
291
  numbers = parseFloats( data );
323
-
324
292
  for ( let j = 0, jl = numbers.length; j < jl; j += 4 ) {
325
293
 
326
294
  path.quadraticCurveTo( numbers[ j + 0 ], numbers[ j + 1 ], numbers[ j + 2 ], numbers[ j + 3 ] );
@@ -333,10 +301,8 @@
333
301
  }
334
302
 
335
303
  break;
336
-
337
304
  case 'T':
338
305
  numbers = parseFloats( data );
339
-
340
306
  for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) {
341
307
 
342
308
  const rx = getReflection( point.x, control.x );
@@ -351,10 +317,8 @@
351
317
  }
352
318
 
353
319
  break;
354
-
355
320
  case 'A':
356
321
  numbers = parseFloats( data, [ 3, 4 ], 7 );
357
-
358
322
  for ( let j = 0, jl = numbers.length; j < jl; j += 7 ) {
359
323
 
360
324
  // skip command if start point == end point
@@ -370,17 +334,14 @@
370
334
  }
371
335
 
372
336
  break;
373
-
374
337
  case 'm':
375
338
  numbers = parseFloats( data );
376
-
377
339
  for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) {
378
340
 
379
341
  point.x += numbers[ j + 0 ];
380
342
  point.y += numbers[ j + 1 ];
381
343
  control.x = point.x;
382
344
  control.y = point.y;
383
-
384
345
  if ( j === 0 ) {
385
346
 
386
347
  path.moveTo( point.x, point.y );
@@ -396,10 +357,8 @@
396
357
  }
397
358
 
398
359
  break;
399
-
400
360
  case 'h':
401
361
  numbers = parseFloats( data );
402
-
403
362
  for ( let j = 0, jl = numbers.length; j < jl; j ++ ) {
404
363
 
405
364
  point.x += numbers[ j ];
@@ -411,10 +370,8 @@
411
370
  }
412
371
 
413
372
  break;
414
-
415
373
  case 'v':
416
374
  numbers = parseFloats( data );
417
-
418
375
  for ( let j = 0, jl = numbers.length; j < jl; j ++ ) {
419
376
 
420
377
  point.y += numbers[ j ];
@@ -426,10 +383,8 @@
426
383
  }
427
384
 
428
385
  break;
429
-
430
386
  case 'l':
431
387
  numbers = parseFloats( data );
432
-
433
388
  for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) {
434
389
 
435
390
  point.x += numbers[ j + 0 ];
@@ -442,10 +397,8 @@
442
397
  }
443
398
 
444
399
  break;
445
-
446
400
  case 'c':
447
401
  numbers = parseFloats( data );
448
-
449
402
  for ( let j = 0, jl = numbers.length; j < jl; j += 6 ) {
450
403
 
451
404
  path.bezierCurveTo( point.x + numbers[ j + 0 ], point.y + numbers[ j + 1 ], point.x + numbers[ j + 2 ], point.y + numbers[ j + 3 ], point.x + numbers[ j + 4 ], point.y + numbers[ j + 5 ] );
@@ -458,10 +411,8 @@
458
411
  }
459
412
 
460
413
  break;
461
-
462
414
  case 's':
463
415
  numbers = parseFloats( data );
464
-
465
416
  for ( let j = 0, jl = numbers.length; j < jl; j += 4 ) {
466
417
 
467
418
  path.bezierCurveTo( getReflection( point.x, control.x ), getReflection( point.y, control.y ), point.x + numbers[ j + 0 ], point.y + numbers[ j + 1 ], point.x + numbers[ j + 2 ], point.y + numbers[ j + 3 ] );
@@ -474,10 +425,8 @@
474
425
  }
475
426
 
476
427
  break;
477
-
478
428
  case 'q':
479
429
  numbers = parseFloats( data );
480
-
481
430
  for ( let j = 0, jl = numbers.length; j < jl; j += 4 ) {
482
431
 
483
432
  path.quadraticCurveTo( point.x + numbers[ j + 0 ], point.y + numbers[ j + 1 ], point.x + numbers[ j + 2 ], point.y + numbers[ j + 3 ] );
@@ -490,10 +439,8 @@
490
439
  }
491
440
 
492
441
  break;
493
-
494
442
  case 't':
495
443
  numbers = parseFloats( data );
496
-
497
444
  for ( let j = 0, jl = numbers.length; j < jl; j += 2 ) {
498
445
 
499
446
  const rx = getReflection( point.x, control.x );
@@ -508,10 +455,8 @@
508
455
  }
509
456
 
510
457
  break;
511
-
512
458
  case 'a':
513
459
  numbers = parseFloats( data, [ 3, 4 ], 7 );
514
-
515
460
  for ( let j = 0, jl = numbers.length; j < jl; j += 7 ) {
516
461
 
517
462
  // skip command if no displacement
@@ -527,11 +472,9 @@
527
472
  }
528
473
 
529
474
  break;
530
-
531
475
  case 'Z':
532
476
  case 'z':
533
477
  path.currentPath.autoClose = true;
534
-
535
478
  if ( path.currentPath.curves.length > 0 ) {
536
479
 
537
480
  // Reset point to beginning of THREE.Path
@@ -542,12 +485,12 @@
542
485
  }
543
486
 
544
487
  break;
545
-
546
488
  default:
547
489
  console.warn( command );
548
490
 
549
- } // console.log( type, parseFloats( data ), parseFloats( data ).length )
491
+ }
550
492
 
493
+ // console.log( type, parseFloats( data ), parseFloats( data ).length )
551
494
 
552
495
  doSetFirstPoint = false;
553
496
 
@@ -560,13 +503,11 @@
560
503
  function parseCSSStylesheet( node ) {
561
504
 
562
505
  if ( ! node.sheet || ! node.sheet.cssRules || ! node.sheet.cssRules.length ) return;
563
-
564
506
  for ( let i = 0; i < node.sheet.cssRules.length; i ++ ) {
565
507
 
566
508
  const stylesheet = node.sheet.cssRules[ i ];
567
509
  if ( stylesheet.type !== 1 ) continue;
568
510
  const selectorList = stylesheet.selectorText.split( /,/gm ).filter( Boolean ).map( i => i.trim() );
569
-
570
511
  for ( let j = 0; j < selectorList.length; j ++ ) {
571
512
 
572
513
  // Remove empty rules
@@ -578,6 +519,7 @@
578
519
  }
579
520
 
580
521
  }
522
+
581
523
  /**
582
524
  * https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
583
525
  * https://mortoray.com/2017/02/16/rendering-an-svg-elliptical-arc-as-bezier-curves/ Appendix: Endpoint to center arc conversion
@@ -587,7 +529,6 @@
587
529
  * aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation
588
530
  */
589
531
 
590
-
591
532
  function parseArcCommand( path, rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, start, end ) {
592
533
 
593
534
  if ( rx == 0 || ry == 0 ) {
@@ -598,23 +539,26 @@
598
539
 
599
540
  }
600
541
 
601
- x_axis_rotation = x_axis_rotation * Math.PI / 180; // Ensure radii are positive
542
+ x_axis_rotation = x_axis_rotation * Math.PI / 180;
602
543
 
544
+ // Ensure radii are positive
603
545
  rx = Math.abs( rx );
604
- ry = Math.abs( ry ); // Compute (x1', y1')
546
+ ry = Math.abs( ry );
605
547
 
548
+ // Compute (x1', y1')
606
549
  const dx2 = ( start.x - end.x ) / 2.0;
607
550
  const dy2 = ( start.y - end.y ) / 2.0;
608
551
  const x1p = Math.cos( x_axis_rotation ) * dx2 + Math.sin( x_axis_rotation ) * dy2;
609
- const y1p = - Math.sin( x_axis_rotation ) * dx2 + Math.cos( x_axis_rotation ) * dy2; // Compute (cx', cy')
552
+ const y1p = - Math.sin( x_axis_rotation ) * dx2 + Math.cos( x_axis_rotation ) * dy2;
610
553
 
554
+ // Compute (cx', cy')
611
555
  let rxs = rx * rx;
612
556
  let rys = ry * ry;
613
557
  const x1ps = x1p * x1p;
614
- const y1ps = y1p * y1p; // Ensure radii are large enough
558
+ const y1ps = y1p * y1p;
615
559
 
560
+ // Ensure radii are large enough
616
561
  const cr = x1ps / rxs + y1ps / rys;
617
-
618
562
  if ( cr > 1 ) {
619
563
 
620
564
  // scale up rx,ry equally so cr == 1
@@ -631,11 +575,13 @@
631
575
  let q = Math.sqrt( Math.max( 0, pq ) );
632
576
  if ( large_arc_flag === sweep_flag ) q = - q;
633
577
  const cxp = q * rx * y1p / ry;
634
- const cyp = - q * ry * x1p / rx; // Step 3: Compute (cx, cy) from (cx', cy')
578
+ const cyp = - q * ry * x1p / rx;
635
579
 
580
+ // Step 3: Compute (cx, cy) from (cx', cy')
636
581
  const cx = Math.cos( x_axis_rotation ) * cxp - Math.sin( x_axis_rotation ) * cyp + ( start.x + end.x ) / 2;
637
- const cy = Math.sin( x_axis_rotation ) * cxp + Math.cos( x_axis_rotation ) * cyp + ( start.y + end.y ) / 2; // Step 4: Compute θ1 and Δθ
582
+ const cy = Math.sin( x_axis_rotation ) * cxp + Math.cos( x_axis_rotation ) * cyp + ( start.y + end.y ) / 2;
638
583
 
584
+ // Step 4: Compute θ1 and Δθ
639
585
  const theta = svgAngle( 1, 0, ( x1p - cxp ) / rx, ( y1p - cyp ) / ry );
640
586
  const delta = svgAngle( ( x1p - cxp ) / rx, ( y1p - cyp ) / ry, ( - x1p - cxp ) / rx, ( - y1p - cyp ) / ry ) % ( Math.PI * 2 );
641
587
  path.currentPath.absellipse( cx, cy, rx, ry, theta, theta + delta, sweep_flag === 0, x_axis_rotation );
@@ -647,17 +593,15 @@
647
593
  const dot = ux * vx + uy * vy;
648
594
  const len = Math.sqrt( ux * ux + uy * uy ) * Math.sqrt( vx * vx + vy * vy );
649
595
  let ang = Math.acos( Math.max( - 1, Math.min( 1, dot / len ) ) ); // floating point precision, slightly over values appear
650
-
651
596
  if ( ux * vy - uy * vx < 0 ) ang = - ang;
652
597
  return ang;
653
598
 
654
599
  }
600
+
655
601
  /*
656
602
  * According to https://www.w3.org/TR/SVG/shapes.html#RectElementRXAttribute
657
603
  * rounded corner should be rendered to elliptical arc, but bezier curve does the job well enough
658
604
  */
659
-
660
-
661
605
  function parseRectNode( node ) {
662
606
 
663
607
  const x = parseFloatWithUnits( node.getAttribute( 'x' ) || 0 );
@@ -665,43 +609,42 @@
665
609
  const rx = parseFloatWithUnits( node.getAttribute( 'rx' ) || node.getAttribute( 'ry' ) || 0 );
666
610
  const ry = parseFloatWithUnits( node.getAttribute( 'ry' ) || node.getAttribute( 'rx' ) || 0 );
667
611
  const w = parseFloatWithUnits( node.getAttribute( 'width' ) );
668
- const h = parseFloatWithUnits( node.getAttribute( 'height' ) ); // Ellipse arc to Bezier approximation Coefficient (Inversed). See:
669
- // https://spencermortensen.com/articles/bezier-circle/
612
+ const h = parseFloatWithUnits( node.getAttribute( 'height' ) );
670
613
 
614
+ // Ellipse arc to Bezier approximation Coefficient (Inversed). See:
615
+ // https://spencermortensen.com/articles/bezier-circle/
671
616
  const bci = 1 - 0.551915024494;
672
- const path = new THREE.ShapePath(); // top left
617
+ const path = new THREE.ShapePath();
673
618
 
674
- path.moveTo( x + rx, y ); // top right
619
+ // top left
620
+ path.moveTo( x + rx, y );
675
621
 
622
+ // top right
676
623
  path.lineTo( x + w - rx, y );
677
-
678
624
  if ( rx !== 0 || ry !== 0 ) {
679
625
 
680
626
  path.bezierCurveTo( x + w - rx * bci, y, x + w, y + ry * bci, x + w, y + ry );
681
627
 
682
- } // bottom right
683
-
628
+ }
684
629
 
630
+ // bottom right
685
631
  path.lineTo( x + w, y + h - ry );
686
-
687
632
  if ( rx !== 0 || ry !== 0 ) {
688
633
 
689
634
  path.bezierCurveTo( x + w, y + h - ry * bci, x + w - rx * bci, y + h, x + w - rx, y + h );
690
635
 
691
- } // bottom left
692
-
636
+ }
693
637
 
638
+ // bottom left
694
639
  path.lineTo( x + rx, y + h );
695
-
696
640
  if ( rx !== 0 || ry !== 0 ) {
697
641
 
698
642
  path.bezierCurveTo( x + rx * bci, y + h, x, y + h - ry * bci, x, y + h - ry );
699
643
 
700
- } // back to top left
701
-
644
+ }
702
645
 
646
+ // back to top left
703
647
  path.lineTo( x, y + ry );
704
-
705
648
  if ( rx !== 0 || ry !== 0 ) {
706
649
 
707
650
  path.bezierCurveTo( x, y + ry * bci, x + rx * bci, y, x + rx, y );
@@ -718,7 +661,6 @@
718
661
 
719
662
  const x = parseFloatWithUnits( a );
720
663
  const y = parseFloatWithUnits( b );
721
-
722
664
  if ( index === 0 ) {
723
665
 
724
666
  path.moveTo( x, y );
@@ -748,7 +690,6 @@
748
690
 
749
691
  const x = parseFloatWithUnits( a );
750
692
  const y = parseFloatWithUnits( b );
751
-
752
693
  if ( index === 0 ) {
753
694
 
754
695
  path.moveTo( x, y );
@@ -811,19 +752,18 @@
811
752
  path.currentPath.autoClose = false;
812
753
  return path;
813
754
 
814
- } //
755
+ }
815
756
 
757
+ //
816
758
 
817
759
  function parseStyle( node, style ) {
818
760
 
819
761
  style = Object.assign( {}, style ); // clone style
820
762
 
821
763
  let stylesheetStyles = {};
822
-
823
764
  if ( node.hasAttribute( 'class' ) ) {
824
765
 
825
766
  const classSelectors = node.getAttribute( 'class' ).split( /\s/ ).filter( Boolean ).map( i => i.trim() );
826
-
827
767
  for ( let i = 0; i < classSelectors.length; i ++ ) {
828
768
 
829
769
  stylesheetStyles = Object.assign( stylesheetStyles, stylesheets[ '.' + classSelectors[ i ] ] );
@@ -878,15 +818,17 @@
878
818
  addStyle( 'visibility', 'visibility' );
879
819
  return style;
880
820
 
881
- } // http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
821
+ }
882
822
 
823
+ // http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
883
824
 
884
825
  function getReflection( a, b ) {
885
826
 
886
827
  return a - ( b - a );
887
828
 
888
- } // from https://github.com/ppvg/svg-numbers (MIT License)
829
+ }
889
830
 
831
+ // from https://github.com/ppvg/svg-numbers (MIT License)
890
832
 
891
833
  function parseFloats( input, flags, stride ) {
892
834
 
@@ -894,9 +836,9 @@
894
836
 
895
837
  throw new TypeError( 'Invalid input: ' + typeof input );
896
838
 
897
- } // Character groups
898
-
839
+ }
899
840
 
841
+ // Character groups
900
842
  const RE = {
901
843
  SEPARATOR: /[ \t\r\n\,.\-+]/,
902
844
  WHITESPACE: /[ \t\r\n]/,
@@ -906,8 +848,9 @@
906
848
  COMMA: /,/,
907
849
  EXP: /e/i,
908
850
  FLAGS: /[01]/
909
- }; // States
851
+ };
910
852
 
853
+ // States
911
854
  const SEP = 0;
912
855
  const INT = 1;
913
856
  const FLOAT = 2;
@@ -917,7 +860,6 @@
917
860
  let number = '',
918
861
  exponent = '';
919
862
  const result = [];
920
-
921
863
  function throwSyntaxError( current, i, partial ) {
922
864
 
923
865
  const error = new SyntaxError( 'Unexpected character "' + current + '" at index ' + i + '.' );
@@ -941,11 +883,11 @@
941
883
 
942
884
  let current;
943
885
  const length = input.length;
944
-
945
886
  for ( let i = 0; i < length; i ++ ) {
946
887
 
947
- current = input[ i ]; // check for flags
888
+ current = input[ i ];
948
889
 
890
+ // check for flags
949
891
  if ( Array.isArray( flags ) && flags.includes( result.length % stride ) && RE.FLAGS.test( current ) ) {
950
892
 
951
893
  state = INT;
@@ -953,9 +895,9 @@
953
895
  newNumber();
954
896
  continue;
955
897
 
956
- } // parse until next number
957
-
898
+ }
958
899
 
900
+ // parse until next number
959
901
  if ( state === SEP ) {
960
902
 
961
903
  // eat whitespace
@@ -963,9 +905,9 @@
963
905
 
964
906
  continue;
965
907
 
966
- } // start new number
967
-
908
+ }
968
909
 
910
+ // start new number
969
911
  if ( RE.DIGIT.test( current ) || RE.SIGN.test( current ) ) {
970
912
 
971
913
  state = INT;
@@ -980,9 +922,9 @@
980
922
  number = current;
981
923
  continue;
982
924
 
983
- } // throw on double commas (e.g. "1, , 2")
984
-
925
+ }
985
926
 
927
+ // throw on double commas (e.g. "1, , 2")
986
928
  if ( RE.COMMA.test( current ) ) {
987
929
 
988
930
  if ( seenComma ) {
@@ -995,9 +937,9 @@
995
937
 
996
938
  }
997
939
 
998
- } // parse integer part
999
-
940
+ }
1000
941
 
942
+ // parse integer part
1001
943
  if ( state === INT ) {
1002
944
 
1003
945
  if ( RE.DIGIT.test( current ) ) {
@@ -1020,18 +962,18 @@
1020
962
  state = EXP;
1021
963
  continue;
1022
964
 
1023
- } // throw on double signs ("-+1"), but not on sign as separator ("-1-2")
1024
-
965
+ }
1025
966
 
967
+ // throw on double signs ("-+1"), but not on sign as separator ("-1-2")
1026
968
  if ( RE.SIGN.test( current ) && number.length === 1 && RE.SIGN.test( number[ 0 ] ) ) {
1027
969
 
1028
970
  throwSyntaxError( current, i, result );
1029
971
 
1030
972
  }
1031
973
 
1032
- } // parse decimal part
1033
-
974
+ }
1034
975
 
976
+ // parse decimal part
1035
977
  if ( state === FLOAT ) {
1036
978
 
1037
979
  if ( RE.DIGIT.test( current ) ) {
@@ -1046,18 +988,18 @@
1046
988
  state = EXP;
1047
989
  continue;
1048
990
 
1049
- } // throw on double decimal points (e.g. "1..2")
1050
-
991
+ }
1051
992
 
993
+ // throw on double decimal points (e.g. "1..2")
1052
994
  if ( RE.POINT.test( current ) && number[ number.length - 1 ] === '.' ) {
1053
995
 
1054
996
  throwSyntaxError( current, i, result );
1055
997
 
1056
998
  }
1057
999
 
1058
- } // parse exponent part
1059
-
1000
+ }
1060
1001
 
1002
+ // parse exponent part
1061
1003
  if ( state === EXP ) {
1062
1004
 
1063
1005
  if ( RE.DIGIT.test( current ) ) {
@@ -1084,9 +1026,9 @@
1084
1026
 
1085
1027
  }
1086
1028
 
1087
- } // end of number
1088
-
1029
+ }
1089
1030
 
1031
+ // end of number
1090
1032
  if ( RE.WHITESPACE.test( current ) ) {
1091
1033
 
1092
1034
  newNumber();
@@ -1117,17 +1059,19 @@
1117
1059
 
1118
1060
  }
1119
1061
 
1120
- } // add the last number found (if any)
1121
-
1062
+ }
1122
1063
 
1064
+ // add the last number found (if any)
1123
1065
  newNumber();
1124
1066
  return result;
1125
1067
 
1126
- } // Units
1068
+ }
1127
1069
 
1070
+ // Units
1128
1071
 
1129
- const units = [ 'mm', 'cm', 'in', 'pt', 'pc', 'px' ]; // Conversion: [ fromUnit ][ toUnit ] (-1 means dpi dependent)
1072
+ const units = [ 'mm', 'cm', 'in', 'pt', 'pc', 'px' ];
1130
1073
 
1074
+ // Conversion: [ fromUnit ][ toUnit ] (-1 means dpi dependent)
1131
1075
  const unitConversion = {
1132
1076
  'mm': {
1133
1077
  'mm': 1,
@@ -1173,17 +1117,14 @@
1173
1117
  'px': 1
1174
1118
  }
1175
1119
  };
1176
-
1177
1120
  function parseFloatWithUnits( string ) {
1178
1121
 
1179
1122
  let theUnit = 'px';
1180
-
1181
1123
  if ( typeof string === 'string' || string instanceof String ) {
1182
1124
 
1183
1125
  for ( let i = 0, n = units.length; i < n; i ++ ) {
1184
1126
 
1185
1127
  const u = units[ i ];
1186
-
1187
1128
  if ( string.endsWith( u ) ) {
1188
1129
 
1189
1130
  theUnit = u;
@@ -1197,19 +1138,19 @@
1197
1138
  }
1198
1139
 
1199
1140
  let scale = undefined;
1200
-
1201
1141
  if ( theUnit === 'px' && scope.defaultUnit !== 'px' ) {
1202
1142
 
1203
1143
  // Conversion scale from pixels to inches, then to default units
1144
+
1204
1145
  scale = unitConversion[ 'in' ][ scope.defaultUnit ] / scope.defaultDPI;
1205
1146
 
1206
1147
  } else {
1207
1148
 
1208
1149
  scale = unitConversion[ theUnit ][ scope.defaultUnit ];
1209
-
1210
1150
  if ( scale < 0 ) {
1211
1151
 
1212
1152
  // Conversion scale to pixels
1153
+
1213
1154
  scale = unitConversion[ theUnit ][ 'in' ] * scope.defaultDPI;
1214
1155
 
1215
1156
  }
@@ -1218,8 +1159,9 @@
1218
1159
 
1219
1160
  return scale * parseFloat( string );
1220
1161
 
1221
- } // Transforms
1162
+ }
1222
1163
 
1164
+ // Transforms
1223
1165
 
1224
1166
  function getNodeTransform( node ) {
1225
1167
 
@@ -1230,7 +1172,6 @@
1230
1172
  }
1231
1173
 
1232
1174
  const transform = parseNodeTransform( node );
1233
-
1234
1175
  if ( transformStack.length > 0 ) {
1235
1176
 
1236
1177
  transform.premultiply( transformStack[ transformStack.length - 1 ] );
@@ -1247,7 +1188,6 @@
1247
1188
 
1248
1189
  const transform = new THREE.Matrix3();
1249
1190
  const currentTransform = tempTransform0;
1250
-
1251
1191
  if ( node.nodeName === 'use' && ( node.hasAttribute( 'x' ) || node.hasAttribute( 'y' ) ) ) {
1252
1192
 
1253
1193
  const tx = parseFloatWithUnits( node.getAttribute( 'x' ) );
@@ -1259,20 +1199,17 @@
1259
1199
  if ( node.hasAttribute( 'transform' ) ) {
1260
1200
 
1261
1201
  const transformsTexts = node.getAttribute( 'transform' ).split( ')' );
1262
-
1263
1202
  for ( let tIndex = transformsTexts.length - 1; tIndex >= 0; tIndex -- ) {
1264
1203
 
1265
1204
  const transformText = transformsTexts[ tIndex ].trim();
1266
1205
  if ( transformText === '' ) continue;
1267
1206
  const openParPos = transformText.indexOf( '(' );
1268
1207
  const closeParPos = transformText.length;
1269
-
1270
1208
  if ( openParPos > 0 && openParPos < closeParPos ) {
1271
1209
 
1272
1210
  const transformType = transformText.slice( 0, openParPos );
1273
1211
  const array = parseFloats( transformText.slice( openParPos + 1 ) );
1274
1212
  currentTransform.identity();
1275
-
1276
1213
  switch ( transformType ) {
1277
1214
 
1278
1215
  case 'translate':
@@ -1280,7 +1217,6 @@
1280
1217
 
1281
1218
  const tx = array[ 0 ];
1282
1219
  let ty = 0;
1283
-
1284
1220
  if ( array.length >= 2 ) {
1285
1221
 
1286
1222
  ty = array[ 1 ];
@@ -1292,41 +1228,38 @@
1292
1228
  }
1293
1229
 
1294
1230
  break;
1295
-
1296
1231
  case 'rotate':
1297
1232
  if ( array.length >= 1 ) {
1298
1233
 
1299
1234
  let angle = 0;
1300
1235
  let cx = 0;
1301
- let cy = 0; // Angle
1302
-
1303
- angle = - array[ 0 ] * Math.PI / 180;
1236
+ let cy = 0;
1304
1237
 
1238
+ // Angle
1239
+ angle = array[ 0 ] * Math.PI / 180;
1305
1240
  if ( array.length >= 3 ) {
1306
1241
 
1307
1242
  // Center x, y
1308
1243
  cx = array[ 1 ];
1309
1244
  cy = array[ 2 ];
1310
1245
 
1311
- } // Rotate around center (cx, cy)
1312
-
1246
+ }
1313
1247
 
1314
- tempTransform1.identity().translate( - cx, - cy );
1315
- tempTransform2.identity().rotate( angle );
1248
+ // Rotate around center (cx, cy)
1249
+ tempTransform1.makeTranslation( - cx, - cy );
1250
+ tempTransform2.makeRotation( angle );
1316
1251
  tempTransform3.multiplyMatrices( tempTransform2, tempTransform1 );
1317
- tempTransform1.identity().translate( cx, cy );
1252
+ tempTransform1.makeTranslation( cx, cy );
1318
1253
  currentTransform.multiplyMatrices( tempTransform1, tempTransform3 );
1319
1254
 
1320
1255
  }
1321
1256
 
1322
1257
  break;
1323
-
1324
1258
  case 'scale':
1325
1259
  if ( array.length >= 1 ) {
1326
1260
 
1327
1261
  const scaleX = array[ 0 ];
1328
1262
  let scaleY = scaleX;
1329
-
1330
1263
  if ( array.length >= 2 ) {
1331
1264
 
1332
1265
  scaleY = array[ 1 ];
@@ -1338,7 +1271,6 @@
1338
1271
  }
1339
1272
 
1340
1273
  break;
1341
-
1342
1274
  case 'skewX':
1343
1275
  if ( array.length === 1 ) {
1344
1276
 
@@ -1347,7 +1279,6 @@
1347
1279
  }
1348
1280
 
1349
1281
  break;
1350
-
1351
1282
  case 'skewY':
1352
1283
  if ( array.length === 1 ) {
1353
1284
 
@@ -1356,7 +1287,6 @@
1356
1287
  }
1357
1288
 
1358
1289
  break;
1359
-
1360
1290
  case 'matrix':
1361
1291
  if ( array.length === 6 ) {
1362
1292
 
@@ -1389,18 +1319,99 @@
1389
1319
 
1390
1320
  }
1391
1321
 
1392
- const isRotated = isTransformRotated( m );
1393
- const subPaths = path.subPaths;
1322
+ function transfEllipseGeneric( curve ) {
1323
+
1324
+ // For math description see:
1325
+ // https://math.stackexchange.com/questions/4544164
1326
+
1327
+ const a = curve.xRadius;
1328
+ const b = curve.yRadius;
1329
+ const cosTheta = Math.cos( curve.aRotation );
1330
+ const sinTheta = Math.sin( curve.aRotation );
1331
+ const v1 = new THREE.Vector3( a * cosTheta, a * sinTheta, 0 );
1332
+ const v2 = new THREE.Vector3( - b * sinTheta, b * cosTheta, 0 );
1333
+ const f1 = v1.applyMatrix3( m );
1334
+ const f2 = v2.applyMatrix3( m );
1335
+ const mF = tempTransform0.set( f1.x, f2.x, 0, f1.y, f2.y, 0, 0, 0, 1 );
1336
+ const mFInv = tempTransform1.copy( mF ).invert();
1337
+ const mFInvT = tempTransform2.copy( mFInv ).transpose();
1338
+ const mQ = mFInvT.multiply( mFInv );
1339
+ const mQe = mQ.elements;
1340
+ const ed = eigenDecomposition( mQe[ 0 ], mQe[ 1 ], mQe[ 4 ] );
1341
+ const rt1sqrt = Math.sqrt( ed.rt1 );
1342
+ const rt2sqrt = Math.sqrt( ed.rt2 );
1343
+ curve.xRadius = 1 / rt1sqrt;
1344
+ curve.yRadius = 1 / rt2sqrt;
1345
+ curve.aRotation = Math.atan2( ed.sn, ed.cs );
1346
+ const isFullEllipse = ( curve.aEndAngle - curve.aStartAngle ) % ( 2 * Math.PI ) < Number.EPSILON;
1347
+
1348
+ // Do not touch angles of a full ellipse because after transformation they
1349
+ // would converge to a sinle value effectively removing the whole curve
1350
+
1351
+ if ( ! isFullEllipse ) {
1352
+
1353
+ const mDsqrt = tempTransform1.set( rt1sqrt, 0, 0, 0, rt2sqrt, 0, 0, 0, 1 );
1354
+ const mRT = tempTransform2.set( ed.cs, ed.sn, 0, - ed.sn, ed.cs, 0, 0, 0, 1 );
1355
+ const mDRF = mDsqrt.multiply( mRT ).multiply( mF );
1356
+ const transformAngle = phi => {
1357
+
1358
+ const {
1359
+ x: cosR,
1360
+ y: sinR
1361
+ } = new THREE.Vector3( Math.cos( phi ), Math.sin( phi ), 0 ).applyMatrix3( mDRF );
1362
+ return Math.atan2( sinR, cosR );
1363
+
1364
+ };
1365
+
1366
+ curve.aStartAngle = transformAngle( curve.aStartAngle );
1367
+ curve.aEndAngle = transformAngle( curve.aEndAngle );
1368
+ if ( isTransformFlipped( m ) ) {
1369
+
1370
+ curve.aClockwise = ! curve.aClockwise;
1371
+
1372
+ }
1373
+
1374
+ }
1375
+
1376
+ }
1377
+
1378
+ function transfEllipseNoSkew( curve ) {
1394
1379
 
1380
+ // Faster shortcut if no skew is applied
1381
+ // (e.g, a euclidean transform of a group containing the ellipse)
1382
+
1383
+ const sx = getTransformScaleX( m );
1384
+ const sy = getTransformScaleY( m );
1385
+ curve.xRadius *= sx;
1386
+ curve.yRadius *= sy;
1387
+
1388
+ // Extract rotation angle from the matrix of form:
1389
+ //
1390
+ // | cosθ sx -sinθ sy |
1391
+ // | sinθ sx cosθ sy |
1392
+ //
1393
+ // Remembering that tanθ = sinθ / cosθ; and that
1394
+ // `sx`, `sy`, or both might be zero.
1395
+ const theta = sx > Number.EPSILON ? Math.atan2( m.elements[ 1 ], m.elements[ 0 ] ) : Math.atan2( - m.elements[ 3 ], m.elements[ 4 ] );
1396
+ curve.aRotation += theta;
1397
+ if ( isTransformFlipped( m ) ) {
1398
+
1399
+ curve.aStartAngle *= - 1;
1400
+ curve.aEndAngle *= - 1;
1401
+ curve.aClockwise = ! curve.aClockwise;
1402
+
1403
+ }
1404
+
1405
+ }
1406
+
1407
+ const subPaths = path.subPaths;
1395
1408
  for ( let i = 0, n = subPaths.length; i < n; i ++ ) {
1396
1409
 
1397
1410
  const subPath = subPaths[ i ];
1398
1411
  const curves = subPath.curves;
1399
-
1400
1412
  for ( let j = 0; j < curves.length; j ++ ) {
1401
1413
 
1402
1414
  const curve = curves[ j ];
1403
-
1404
1415
  if ( curve.isLineCurve ) {
1405
1416
 
1406
1417
  transfVec2( curve.v1 );
@@ -1421,18 +1432,24 @@
1421
1432
 
1422
1433
  } else if ( curve.isEllipseCurve ) {
1423
1434
 
1424
- if ( isRotated ) {
1425
-
1426
- console.warn( 'SVGLoader: Elliptic arc or ellipse rotation or skewing is not implemented.' );
1427
-
1428
- }
1435
+ // Transform ellipse center point
1429
1436
 
1430
1437
  tempV2.set( curve.aX, curve.aY );
1431
1438
  transfVec2( tempV2 );
1432
1439
  curve.aX = tempV2.x;
1433
1440
  curve.aY = tempV2.y;
1434
- curve.xRadius *= getTransformScaleX( m );
1435
- curve.yRadius *= getTransformScaleY( m );
1441
+
1442
+ // Transform ellipse shape parameters
1443
+
1444
+ if ( isTransformSkewed( m ) ) {
1445
+
1446
+ transfEllipseGeneric( curve );
1447
+
1448
+ } else {
1449
+
1450
+ transfEllipseNoSkew( curve );
1451
+
1452
+ }
1436
1453
 
1437
1454
  }
1438
1455
 
@@ -1442,9 +1459,23 @@
1442
1459
 
1443
1460
  }
1444
1461
 
1445
- function isTransformRotated( m ) {
1462
+ function isTransformFlipped( m ) {
1463
+
1464
+ const te = m.elements;
1465
+ return te[ 0 ] * te[ 4 ] - te[ 1 ] * te[ 3 ] < 0;
1466
+
1467
+ }
1468
+
1469
+ function isTransformSkewed( m ) {
1470
+
1471
+ const te = m.elements;
1472
+ const basisDot = te[ 0 ] * te[ 3 ] + te[ 1 ] * te[ 4 ];
1446
1473
 
1447
- return m.elements[ 1 ] !== 0 || m.elements[ 3 ] !== 0;
1474
+ // Shortcut for trivial rotations and transformations
1475
+ if ( basisDot === 0 ) return false;
1476
+ const sx = getTransformScaleX( m );
1477
+ const sy = getTransformScaleY( m );
1478
+ return Math.abs( basisDot / ( sx * sy ) ) > Number.EPSILON;
1448
1479
 
1449
1480
  }
1450
1481
 
@@ -1460,8 +1491,92 @@
1460
1491
  const te = m.elements;
1461
1492
  return Math.sqrt( te[ 3 ] * te[ 3 ] + te[ 4 ] * te[ 4 ] );
1462
1493
 
1463
- } //
1494
+ }
1495
+
1496
+ // Calculates the eigensystem of a real symmetric 2x2 matrix
1497
+ // [ A B ]
1498
+ // [ B C ]
1499
+ // in the form
1500
+ // [ A B ] = [ cs -sn ] [ rt1 0 ] [ cs sn ]
1501
+ // [ B C ] [ sn cs ] [ 0 rt2 ] [ -sn cs ]
1502
+ // where rt1 >= rt2.
1503
+ //
1504
+ // Adapted from: https://www.mpi-hd.mpg.de/personalhomes/globes/3x3/index.html
1505
+ // -> Algorithms for real symmetric matrices -> Analytical (2x2 symmetric)
1506
+ function eigenDecomposition( A, B, C ) {
1507
+
1508
+ let rt1, rt2, cs, sn, t;
1509
+ const sm = A + C;
1510
+ const df = A - C;
1511
+ const rt = Math.sqrt( df * df + 4 * B * B );
1512
+ if ( sm > 0 ) {
1513
+
1514
+ rt1 = 0.5 * ( sm + rt );
1515
+ t = 1 / rt1;
1516
+ rt2 = A * t * C - B * t * B;
1517
+
1518
+ } else if ( sm < 0 ) {
1519
+
1520
+ rt2 = 0.5 * ( sm - rt );
1521
+
1522
+ } else {
1523
+
1524
+ // This case needs to be treated separately to avoid div by 0
1464
1525
 
1526
+ rt1 = 0.5 * rt;
1527
+ rt2 = - 0.5 * rt;
1528
+
1529
+ }
1530
+
1531
+ // Calculate eigenvectors
1532
+
1533
+ if ( df > 0 ) {
1534
+
1535
+ cs = df + rt;
1536
+
1537
+ } else {
1538
+
1539
+ cs = df - rt;
1540
+
1541
+ }
1542
+
1543
+ if ( Math.abs( cs ) > 2 * Math.abs( B ) ) {
1544
+
1545
+ t = - 2 * B / cs;
1546
+ sn = 1 / Math.sqrt( 1 + t * t );
1547
+ cs = t * sn;
1548
+
1549
+ } else if ( Math.abs( B ) === 0 ) {
1550
+
1551
+ cs = 1;
1552
+ sn = 0;
1553
+
1554
+ } else {
1555
+
1556
+ t = - 0.5 * cs / B;
1557
+ cs = 1 / Math.sqrt( 1 + t * t );
1558
+ sn = t * cs;
1559
+
1560
+ }
1561
+
1562
+ if ( df > 0 ) {
1563
+
1564
+ t = cs;
1565
+ cs = - sn;
1566
+ sn = t;
1567
+
1568
+ }
1569
+
1570
+ return {
1571
+ rt1,
1572
+ rt2,
1573
+ cs,
1574
+ sn
1575
+ };
1576
+
1577
+ }
1578
+
1579
+ //
1465
1580
 
1466
1581
  const paths = [];
1467
1582
  const stylesheets = {};
@@ -1487,16 +1602,17 @@
1487
1602
  const data = {
1488
1603
  paths: paths,
1489
1604
  xml: xml.documentElement
1490
- }; // console.log( paths );
1605
+ };
1491
1606
 
1607
+ // console.log( paths );
1492
1608
  return data;
1493
1609
 
1494
1610
  }
1495
-
1496
1611
  static createShapes( shapePath ) {
1497
1612
 
1498
1613
  // Param shapePath: a shapepath as returned by the parse function of this class
1499
1614
  // Returns THREE.Shape object
1615
+
1500
1616
  const BIGNUMBER = 999999999;
1501
1617
  const IntersectionLocationType = {
1502
1618
  ORIGIN: 0,
@@ -1511,7 +1627,6 @@
1511
1627
  loc: IntersectionLocationType.ORIGIN,
1512
1628
  t: 0
1513
1629
  };
1514
-
1515
1630
  function findEdgeIntersection( a0, a1, b0, b1 ) {
1516
1631
 
1517
1632
  const x1 = a0.x;
@@ -1527,20 +1642,21 @@
1527
1642
  const denom = ( y4 - y3 ) * ( x2 - x1 ) - ( x4 - x3 ) * ( y2 - y1 );
1528
1643
  const t1 = nom1 / denom;
1529
1644
  const t2 = nom2 / denom;
1530
-
1531
1645
  if ( denom === 0 && nom1 !== 0 || t1 <= 0 || t1 >= 1 || t2 < 0 || t2 > 1 ) {
1532
1646
 
1533
1647
  //1. lines are parallel or edges don't intersect
1648
+
1534
1649
  return null;
1535
1650
 
1536
1651
  } else if ( nom1 === 0 && denom === 0 ) {
1537
1652
 
1538
1653
  //2. lines are colinear
1654
+
1539
1655
  //check if endpoints of edge2 (b0-b1) lies on edge1 (a0-a1)
1540
1656
  for ( let i = 0; i < 2; i ++ ) {
1541
1657
 
1542
- classifyPoint( i === 0 ? b0 : b1, a0, a1 ); //find position of this endpoints relatively to edge1
1543
-
1658
+ classifyPoint( i === 0 ? b0 : b1, a0, a1 );
1659
+ //find position of this endpoints relatively to edge1
1544
1660
  if ( classifyResult.loc == IntersectionLocationType.ORIGIN ) {
1545
1661
 
1546
1662
  const point = i === 0 ? b0 : b1;
@@ -1569,10 +1685,10 @@
1569
1685
  } else {
1570
1686
 
1571
1687
  //3. edges intersect
1688
+
1572
1689
  for ( let i = 0; i < 2; i ++ ) {
1573
1690
 
1574
1691
  classifyPoint( i === 0 ? b0 : b1, a0, a1 );
1575
-
1576
1692
  if ( classifyResult.loc == IntersectionLocationType.ORIGIN ) {
1577
1693
 
1578
1694
  const point = i === 0 ? b0 : b1;
@@ -1605,7 +1721,6 @@
1605
1721
  const bx = p.x - edgeStart.x;
1606
1722
  const by = p.y - edgeStart.y;
1607
1723
  const sa = ax * by - bx * ay;
1608
-
1609
1724
  if ( p.x === edgeStart.x && p.y === edgeStart.y ) {
1610
1725
 
1611
1726
  classifyResult.loc = IntersectionLocationType.ORIGIN;
@@ -1651,7 +1766,6 @@
1651
1766
  }
1652
1767
 
1653
1768
  let t;
1654
-
1655
1769
  if ( ax !== 0 ) {
1656
1770
 
1657
1771
  t = bx / ax;
@@ -1671,18 +1785,15 @@
1671
1785
 
1672
1786
  const intersectionsRaw = [];
1673
1787
  const intersections = [];
1674
-
1675
1788
  for ( let index = 1; index < path1.length; index ++ ) {
1676
1789
 
1677
1790
  const path1EdgeStart = path1[ index - 1 ];
1678
1791
  const path1EdgeEnd = path1[ index ];
1679
-
1680
1792
  for ( let index2 = 1; index2 < path2.length; index2 ++ ) {
1681
1793
 
1682
1794
  const path2EdgeStart = path2[ index2 - 1 ];
1683
1795
  const path2EdgeEnd = path2[ index2 ];
1684
1796
  const intersection = findEdgeIntersection( path1EdgeStart, path1EdgeEnd, path2EdgeStart, path2EdgeEnd );
1685
-
1686
1797
  if ( intersection !== null && intersectionsRaw.find( i => i.t <= intersection.t + Number.EPSILON && i.t >= intersection.t - Number.EPSILON ) === undefined ) {
1687
1798
 
1688
1799
  intersectionsRaw.push( intersection );
@@ -1765,11 +1876,11 @@
1765
1876
  }
1766
1877
 
1767
1878
  } );
1768
- const firstXOfPath = baseIntersections[ 0 ].point.x; // build up the path hierarchy
1879
+ const firstXOfPath = baseIntersections[ 0 ].point.x;
1769
1880
 
1881
+ // build up the path hierarchy
1770
1882
  const stack = [];
1771
1883
  let i = 0;
1772
-
1773
1884
  while ( i < otherIntersections.length && otherIntersections[ i ].point.x < firstXOfPath ) {
1774
1885
 
1775
1886
  if ( stack.length > 0 && stack[ stack.length - 1 ] === otherIntersections[ i ].identifier ) {
@@ -1787,7 +1898,6 @@
1787
1898
  }
1788
1899
 
1789
1900
  stack.push( simplePath.identifier );
1790
-
1791
1901
  if ( _fillRule === 'evenodd' ) {
1792
1902
 
1793
1903
  const isHole = stack.length % 2 === 0 ? true : false;
@@ -1804,11 +1914,9 @@
1804
1914
  let isHole = true;
1805
1915
  let isHoleFor = null;
1806
1916
  let lastCWValue = null;
1807
-
1808
1917
  for ( let i = 0; i < stack.length; i ++ ) {
1809
1918
 
1810
1919
  const identifier = stack[ i ];
1811
-
1812
1920
  if ( isHole ) {
1813
1921
 
1814
1922
  lastCWValue = allPaths[ identifier ].isCW;
@@ -1836,13 +1944,15 @@
1836
1944
 
1837
1945
  }
1838
1946
 
1839
- } // check for self intersecting paths
1947
+ }
1948
+
1949
+ // check for self intersecting paths
1840
1950
  // TODO
1951
+
1841
1952
  // check intersecting paths
1842
1953
  // TODO
1843
- // prepare paths for hole detection
1844
-
1845
1954
 
1955
+ // prepare paths for hole detection
1846
1956
  let identifier = 0;
1847
1957
  let scanlineMinX = BIGNUMBER;
1848
1958
  let scanlineMaxX = - BIGNUMBER;
@@ -1852,12 +1962,13 @@
1852
1962
  let maxY = - BIGNUMBER;
1853
1963
  let minY = BIGNUMBER;
1854
1964
  let maxX = - BIGNUMBER;
1855
- let minX = BIGNUMBER; //points.forEach(p => p.y *= -1);
1965
+ let minX = BIGNUMBER;
1966
+
1967
+ //points.forEach(p => p.y *= -1);
1856
1968
 
1857
1969
  for ( let i = 0; i < points.length; i ++ ) {
1858
1970
 
1859
1971
  const p = points[ i ];
1860
-
1861
1972
  if ( p.y > maxY ) {
1862
1973
 
1863
1974
  maxY = p.y;
@@ -1882,9 +1993,9 @@
1882
1993
 
1883
1994
  }
1884
1995
 
1885
- } //
1886
-
1996
+ }
1887
1997
 
1998
+ //
1888
1999
  if ( scanlineMaxX <= maxX ) {
1889
2000
 
1890
2001
  scanlineMaxX = maxX + 1;
@@ -1906,14 +2017,14 @@
1906
2017
  };
1907
2018
 
1908
2019
  } );
1909
- simplePaths = simplePaths.filter( sp => sp.points.length > 1 ); // check if path is solid or a hole
2020
+ simplePaths = simplePaths.filter( sp => sp.points.length > 1 );
1910
2021
 
2022
+ // check if path is solid or a hole
1911
2023
  const isAHole = simplePaths.map( p => isHoleTo( p, simplePaths, scanlineMinX, scanlineMaxX, shapePath.userData?.style.fillRule ) );
1912
2024
  const shapesToReturn = [];
1913
2025
  simplePaths.forEach( p => {
1914
2026
 
1915
2027
  const amIAHole = isAHole[ p.identifier ];
1916
-
1917
2028
  if ( ! amIAHole.isHole ) {
1918
2029
 
1919
2030
  const shape = new THREE.Shape();
@@ -1935,7 +2046,6 @@
1935
2046
  return shapesToReturn;
1936
2047
 
1937
2048
  }
1938
-
1939
2049
  static getStrokeStyle( width, color, lineJoin, lineCap, miterLimit ) {
1940
2050
 
1941
2051
  // Param width: Stroke width
@@ -1944,6 +2054,7 @@
1944
2054
  // Param lineCap: One of "round", "square" or "butt"
1945
2055
  // Param miterLimit: Maximum join length, in multiples of the "width" parameter (join is truncated if it exceeds that distance)
1946
2056
  // Returns style object
2057
+
1947
2058
  width = width !== undefined ? width : 1;
1948
2059
  color = color !== undefined ? color : '#000';
1949
2060
  lineJoin = lineJoin !== undefined ? lineJoin : 'miter';
@@ -1958,7 +2069,6 @@
1958
2069
  };
1959
2070
 
1960
2071
  }
1961
-
1962
2072
  static pointsToStroke( points, style, arcDivisions, minDistance ) {
1963
2073
 
1964
2074
  // Generates a stroke with some witdh around the given path.
@@ -1968,10 +2078,10 @@
1968
2078
  // Params arcDivisions: Arc divisions for round joins and endcaps. (Optional)
1969
2079
  // Param minDistance: Points closer to this distance will be merged. (Optional)
1970
2080
  // Returns THREE.BufferGeometry with stroke triangles (In plane z = 0). UV coordinates are generated ('u' along path. 'v' across it, from left to right)
2081
+
1971
2082
  const vertices = [];
1972
2083
  const normals = [];
1973
2084
  const uvs = [];
1974
-
1975
2085
  if ( SVGLoader.pointsToStrokeWithBuffers( points, style, arcDivisions, minDistance, vertices, normals, uvs ) === 0 ) {
1976
2086
 
1977
2087
  return null;
@@ -1985,7 +2095,6 @@
1985
2095
  return geometry;
1986
2096
 
1987
2097
  }
1988
-
1989
2098
  static pointsToStrokeWithBuffers( points, style, arcDivisions, minDistance, vertices, normals, uvs, vertexOffset ) {
1990
2099
 
1991
2100
  // This function can be called to update existing arrays or buffers.
@@ -1994,6 +2103,7 @@
1994
2103
  // Returns number of written vertices / normals / uvs pairs
1995
2104
  // if 'vertices' parameter is undefined no triangles will be generated, but the returned vertices count will still be valid (useful to preallocate the buffers)
1996
2105
  // 'normals' and 'uvs' buffers are optional
2106
+
1997
2107
  const tempV2_1 = new THREE.Vector2();
1998
2108
  const tempV2_2 = new THREE.Vector2();
1999
2109
  const tempV2_3 = new THREE.Vector2();
@@ -2013,8 +2123,9 @@
2013
2123
  const outerPoint = new THREE.Vector2();
2014
2124
  arcDivisions = arcDivisions !== undefined ? arcDivisions : 12;
2015
2125
  minDistance = minDistance !== undefined ? minDistance : 0.001;
2016
- vertexOffset = vertexOffset !== undefined ? vertexOffset : 0; // First ensure there are no duplicated points
2126
+ vertexOffset = vertexOffset !== undefined ? vertexOffset : 0;
2017
2127
 
2128
+ // First ensure there are no duplicated points
2018
2129
  points = removeDuplicatedPoints( points );
2019
2130
  const numPoints = points.length;
2020
2131
  if ( numPoints < 2 ) return 0;
@@ -2032,18 +2143,19 @@
2032
2143
  let initialJoinIsOnLeftSide = false;
2033
2144
  let numVertices = 0;
2034
2145
  let currentCoordinate = vertexOffset * 3;
2035
- let currentCoordinateUV = vertexOffset * 2; // Get initial left and right stroke points
2146
+ let currentCoordinateUV = vertexOffset * 2;
2036
2147
 
2148
+ // Get initial left and right stroke points
2037
2149
  getNormal( points[ 0 ], points[ 1 ], tempV2_1 ).multiplyScalar( strokeWidth2 );
2038
2150
  lastPointL.copy( points[ 0 ] ).sub( tempV2_1 );
2039
2151
  lastPointR.copy( points[ 0 ] ).add( tempV2_1 );
2040
2152
  point0L.copy( lastPointL );
2041
2153
  point0R.copy( lastPointR );
2042
-
2043
2154
  for ( let iPoint = 1; iPoint < numPoints; iPoint ++ ) {
2044
2155
 
2045
- currentPoint = points[ iPoint ]; // Get next point
2156
+ currentPoint = points[ iPoint ];
2046
2157
 
2158
+ // Get next point
2047
2159
  if ( iPoint === numPoints - 1 ) {
2048
2160
 
2049
2161
  if ( isClosed ) {
@@ -2057,9 +2169,9 @@
2057
2169
 
2058
2170
  nextPoint = points[ iPoint + 1 ];
2059
2171
 
2060
- } // Normal of previous segment in tempV2_1
2061
-
2172
+ }
2062
2173
 
2174
+ // Normal of previous segment in tempV2_1
2063
2175
  const normal1 = tempV2_1;
2064
2176
  getNormal( previousPoint, currentPoint, normal1 );
2065
2177
  tempV2_3.copy( normal1 ).multiplyScalar( strokeWidth2 );
@@ -2067,7 +2179,6 @@
2067
2179
  currentPointR.copy( currentPoint ).add( tempV2_3 );
2068
2180
  u1 = u0 + deltaU;
2069
2181
  innerSideModified = false;
2070
-
2071
2182
  if ( nextPoint !== undefined ) {
2072
2183
 
2073
2184
  // Normal of next segment in tempV2_2
@@ -2077,7 +2188,6 @@
2077
2188
  nextPointR.copy( currentPoint ).add( tempV2_3 );
2078
2189
  joinIsOnLeftSide = true;
2079
2190
  tempV2_3.subVectors( nextPoint, previousPoint );
2080
-
2081
2191
  if ( normal1.dot( tempV2_3 ) < 0 ) {
2082
2192
 
2083
2193
  joinIsOnLeftSide = false;
@@ -2087,8 +2197,9 @@
2087
2197
  if ( iPoint === 1 ) initialJoinIsOnLeftSide = joinIsOnLeftSide;
2088
2198
  tempV2_3.subVectors( nextPoint, currentPoint );
2089
2199
  tempV2_3.normalize();
2090
- const dot = Math.abs( normal1.dot( tempV2_3 ) ); // If path is straight, don't create join
2200
+ const dot = Math.abs( normal1.dot( tempV2_3 ) );
2091
2201
 
2202
+ // If path is straight, don't create join
2092
2203
  if ( dot > Number.EPSILON ) {
2093
2204
 
2094
2205
  // Compute inner and outer segment intersections
@@ -2102,8 +2213,8 @@
2102
2213
  tempV2_4.divideScalar( segmentLengthPrev );
2103
2214
  tempV2_6.subVectors( nextPoint, currentPoint );
2104
2215
  const segmentLengthNext = tempV2_6.length();
2105
- tempV2_6.divideScalar( segmentLengthNext ); // Check that previous and next segments doesn't overlap with the innerPoint of intersection
2106
-
2216
+ tempV2_6.divideScalar( segmentLengthNext );
2217
+ // Check that previous and next segments doesn't overlap with the innerPoint of intersection
2107
2218
  if ( tempV2_4.dot( innerPoint ) < segmentLengthPrev && tempV2_6.dot( innerPoint ) < segmentLengthNext ) {
2108
2219
 
2109
2220
  innerSideModified = true;
@@ -2113,7 +2224,6 @@
2113
2224
  outerPoint.copy( tempV2_5 ).add( currentPoint );
2114
2225
  innerPoint.add( currentPoint );
2115
2226
  isMiter = false;
2116
-
2117
2227
  if ( innerSideModified ) {
2118
2228
 
2119
2229
  if ( joinIsOnLeftSide ) {
@@ -2131,6 +2241,7 @@
2131
2241
  } else {
2132
2242
 
2133
2243
  // The segment triangles are generated here if there was overlapping
2244
+
2134
2245
  makeSegmentTriangles();
2135
2246
 
2136
2247
  }
@@ -2140,10 +2251,12 @@
2140
2251
  case 'bevel':
2141
2252
  makeSegmentWithBevelJoin( joinIsOnLeftSide, innerSideModified, u1 );
2142
2253
  break;
2143
-
2144
2254
  case 'round':
2145
2255
  // Segment triangles
2146
- createSegmentTrianglesWithMiddleSection( joinIsOnLeftSide, innerSideModified ); // Join triangles
2256
+
2257
+ createSegmentTrianglesWithMiddleSection( joinIsOnLeftSide, innerSideModified );
2258
+
2259
+ // Join triangles
2147
2260
 
2148
2261
  if ( joinIsOnLeftSide ) {
2149
2262
 
@@ -2156,15 +2269,14 @@
2156
2269
  }
2157
2270
 
2158
2271
  break;
2159
-
2160
2272
  case 'miter':
2161
2273
  case 'miter-clip':
2162
2274
  default:
2163
2275
  const miterFraction = strokeWidth2 * style.strokeMiterLimit / miterLength2;
2164
-
2165
2276
  if ( miterFraction < 1 ) {
2166
2277
 
2167
2278
  // The join miter length exceeds the miter limit
2279
+
2168
2280
  if ( style.strokeLineJoin !== 'miter-clip' ) {
2169
2281
 
2170
2282
  makeSegmentWithBevelJoin( joinIsOnLeftSide, innerSideModified, u1 );
@@ -2173,7 +2285,10 @@
2173
2285
  } else {
2174
2286
 
2175
2287
  // Segment triangles
2176
- createSegmentTrianglesWithMiddleSection( joinIsOnLeftSide, innerSideModified ); // Miter-clip join triangles
2288
+
2289
+ createSegmentTrianglesWithMiddleSection( joinIsOnLeftSide, innerSideModified );
2290
+
2291
+ // Miter-clip join triangles
2177
2292
 
2178
2293
  if ( joinIsOnLeftSide ) {
2179
2294
 
@@ -2210,9 +2325,11 @@
2210
2325
  } else {
2211
2326
 
2212
2327
  // Miter join segment triangles
2328
+
2213
2329
  if ( innerSideModified ) {
2214
2330
 
2215
2331
  // Optimized segment + join triangles
2332
+
2216
2333
  if ( joinIsOnLeftSide ) {
2217
2334
 
2218
2335
  addVertex( lastPointR, u0, 1 );
@@ -2246,6 +2363,7 @@
2246
2363
  } else {
2247
2364
 
2248
2365
  // Add extra miter join triangles
2366
+
2249
2367
  if ( joinIsOnLeftSide ) {
2250
2368
 
2251
2369
  addVertex( currentPointL, u1, 0 );
@@ -2279,6 +2397,7 @@
2279
2397
  } else {
2280
2398
 
2281
2399
  // The segment triangles are generated here when two consecutive points are collinear
2400
+
2282
2401
  makeSegmentTriangles();
2283
2402
 
2284
2403
  }
@@ -2286,6 +2405,7 @@
2286
2405
  } else {
2287
2406
 
2288
2407
  // The segment triangles are generated here if it is the ending segment
2408
+
2289
2409
  makeSegmentTriangles();
2290
2410
 
2291
2411
  }
@@ -2295,8 +2415,9 @@
2295
2415
  // Start line endcap
2296
2416
  addCapGeometry( points[ 0 ], point0L, point0R, joinIsOnLeftSide, true, u0 );
2297
2417
 
2298
- } // Increment loop variables
2418
+ }
2299
2419
 
2420
+ // Increment loop variables
2300
2421
 
2301
2422
  u0 = u1;
2302
2423
  previousPoint = currentPoint;
@@ -2313,9 +2434,9 @@
2313
2434
  } else if ( innerSideModified && vertices ) {
2314
2435
 
2315
2436
  // Modify path first segment vertices to adjust to the segments inner and outer intersections
2437
+
2316
2438
  let lastOuter = outerPoint;
2317
2439
  let lastInner = innerPoint;
2318
-
2319
2440
  if ( initialJoinIsOnLeftSide !== joinIsOnLeftSide ) {
2320
2441
 
2321
2442
  lastOuter = innerPoint;
@@ -2329,7 +2450,6 @@
2329
2450
 
2330
2451
  lastInner.toArray( vertices, 0 * 3 );
2331
2452
  lastInner.toArray( vertices, 3 * 3 );
2332
-
2333
2453
  if ( isMiter ) {
2334
2454
 
2335
2455
  lastOuter.toArray( vertices, 1 * 3 );
@@ -2344,7 +2464,6 @@
2344
2464
 
2345
2465
  lastInner.toArray( vertices, 1 * 3 );
2346
2466
  lastInner.toArray( vertices, 3 * 3 );
2347
-
2348
2467
  if ( isMiter ) {
2349
2468
 
2350
2469
  lastOuter.toArray( vertices, 0 * 3 );
@@ -2357,7 +2476,10 @@
2357
2476
 
2358
2477
  }
2359
2478
 
2360
- return numVertices; // -- End of algorithm
2479
+ return numVertices;
2480
+
2481
+ // -- End of algorithm
2482
+
2361
2483
  // -- Functions
2362
2484
 
2363
2485
  function getNormal( p1, p2, result ) {
@@ -2374,7 +2496,6 @@
2374
2496
  vertices[ currentCoordinate ] = position.x;
2375
2497
  vertices[ currentCoordinate + 1 ] = position.y;
2376
2498
  vertices[ currentCoordinate + 2 ] = 0;
2377
-
2378
2499
  if ( normals ) {
2379
2500
 
2380
2501
  normals[ currentCoordinate ] = 0;
@@ -2384,7 +2505,6 @@
2384
2505
  }
2385
2506
 
2386
2507
  currentCoordinate += 3;
2387
-
2388
2508
  if ( uvs ) {
2389
2509
 
2390
2510
  uvs[ currentCoordinateUV ] = u;
@@ -2403,6 +2523,7 @@
2403
2523
 
2404
2524
  // param p1, p2: Points in the circle arc.
2405
2525
  // p1 and p2 are in clockwise direction.
2526
+
2406
2527
  tempV2_1.copy( p1 ).sub( center ).normalize();
2407
2528
  tempV2_2.copy( p2 ).sub( center ).normalize();
2408
2529
  let angle = Math.PI;
@@ -2410,7 +2531,6 @@
2410
2531
  if ( Math.abs( dot ) < 1 ) angle = Math.abs( Math.acos( dot ) );
2411
2532
  angle /= arcDivisions;
2412
2533
  tempV2_3.copy( p1 );
2413
-
2414
2534
  for ( let i = 0, il = arcDivisions - 1; i < il; i ++ ) {
2415
2535
 
2416
2536
  tempV2_4.copy( tempV2_3 ).rotateAround( center, angle );
@@ -2443,15 +2563,19 @@
2443
2563
  if ( innerSideModified ) {
2444
2564
 
2445
2565
  // Optimized segment + bevel triangles
2566
+
2446
2567
  if ( joinIsOnLeftSide ) {
2447
2568
 
2448
2569
  // THREE.Path segments triangles
2570
+
2449
2571
  addVertex( lastPointR, u0, 1 );
2450
2572
  addVertex( lastPointL, u0, 0 );
2451
2573
  addVertex( currentPointL, u1, 0 );
2452
2574
  addVertex( lastPointR, u0, 1 );
2453
2575
  addVertex( currentPointL, u1, 0 );
2454
- addVertex( innerPoint, u1, 1 ); // Bevel join triangle
2576
+ addVertex( innerPoint, u1, 1 );
2577
+
2578
+ // Bevel join triangle
2455
2579
 
2456
2580
  addVertex( currentPointL, u, 0 );
2457
2581
  addVertex( nextPointL, u, 0 );
@@ -2460,12 +2584,15 @@
2460
2584
  } else {
2461
2585
 
2462
2586
  // THREE.Path segments triangles
2587
+
2463
2588
  addVertex( lastPointR, u0, 1 );
2464
2589
  addVertex( lastPointL, u0, 0 );
2465
2590
  addVertex( currentPointR, u1, 1 );
2466
2591
  addVertex( lastPointL, u0, 0 );
2467
2592
  addVertex( innerPoint, u1, 0 );
2468
- addVertex( currentPointR, u1, 1 ); // Bevel join triangle
2593
+ addVertex( currentPointR, u1, 1 );
2594
+
2595
+ // Bevel join triangle
2469
2596
 
2470
2597
  addVertex( currentPointR, u, 1 );
2471
2598
  addVertex( nextPointR, u, 0 );
@@ -2476,6 +2603,7 @@
2476
2603
  } else {
2477
2604
 
2478
2605
  // Bevel join triangle. The segment triangles are done in the main loop
2606
+
2479
2607
  if ( joinIsOnLeftSide ) {
2480
2608
 
2481
2609
  addVertex( currentPointL, u, 0 );
@@ -2538,6 +2666,7 @@
2538
2666
 
2539
2667
  // param center: End point of the path
2540
2668
  // param p1, p2: Left and right cap points
2669
+
2541
2670
  switch ( style.strokeLineCap ) {
2542
2671
 
2543
2672
  case 'round':
@@ -2552,15 +2681,15 @@
2552
2681
  }
2553
2682
 
2554
2683
  break;
2555
-
2556
2684
  case 'square':
2557
2685
  if ( start ) {
2558
2686
 
2559
2687
  tempV2_1.subVectors( p1, center );
2560
2688
  tempV2_2.set( tempV2_1.y, - tempV2_1.x );
2561
2689
  tempV2_3.addVectors( tempV2_1, tempV2_2 ).add( center );
2562
- tempV2_4.subVectors( tempV2_2, tempV2_1 ).add( center ); // Modify already existing vertices
2690
+ tempV2_4.subVectors( tempV2_2, tempV2_1 ).add( center );
2563
2691
 
2692
+ // Modify already existing vertices
2564
2693
  if ( joinIsOnLeftSide ) {
2565
2694
 
2566
2695
  tempV2_3.toArray( vertices, 1 * 3 );
@@ -2581,8 +2710,9 @@
2581
2710
  tempV2_2.set( tempV2_1.y, - tempV2_1.x );
2582
2711
  tempV2_3.addVectors( tempV2_1, tempV2_2 ).add( center );
2583
2712
  tempV2_4.subVectors( tempV2_2, tempV2_1 ).add( center );
2584
- const vl = vertices.length; // Modify already existing vertices
2713
+ const vl = vertices.length;
2585
2714
 
2715
+ // Modify already existing vertices
2586
2716
  if ( joinIsOnLeftSide ) {
2587
2717
 
2588
2718
  tempV2_3.toArray( vertices, vl - 1 * 3 );
@@ -2600,7 +2730,6 @@
2600
2730
  }
2601
2731
 
2602
2732
  break;
2603
-
2604
2733
  case 'butt':
2605
2734
  default:
2606
2735
  // Nothing to do here
@@ -2614,8 +2743,8 @@
2614
2743
 
2615
2744
  // Creates a new array if necessary with duplicated points removed.
2616
2745
  // This does not remove duplicated initial and ending points of a closed path.
2617
- let dupPoints = false;
2618
2746
 
2747
+ let dupPoints = false;
2619
2748
  for ( let i = 1, n = points.length - 1; i < n; i ++ ) {
2620
2749
 
2621
2750
  if ( points[ i ].distanceTo( points[ i + 1 ] ) < minDistance ) {
@@ -2630,7 +2759,6 @@
2630
2759
  if ( ! dupPoints ) return points;
2631
2760
  const newPoints = [];
2632
2761
  newPoints.push( points[ 0 ] );
2633
-
2634
2762
  for ( let i = 1, n = points.length - 1; i < n; i ++ ) {
2635
2763
 
2636
2764
  if ( points[ i ].distanceTo( points[ i + 1 ] ) >= minDistance ) {