@needle-tools/three 0.145.4 → 0.146.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/build/three.cjs +32586 -35951
- package/build/three.js +32600 -35965
- package/build/three.min.js +6 -7
- package/build/three.module.js +1547 -1154
- package/examples/js/animation/AnimationClipCreator.js +0 -8
- package/examples/js/animation/CCDIKSolver.js +49 -66
- package/examples/js/animation/MMDAnimationHelper.js +66 -137
- package/examples/js/animation/MMDPhysics.js +70 -134
- package/examples/js/cameras/CinematicCamera.js +33 -22
- package/examples/js/controls/ArcballControls.js +138 -405
- package/examples/js/controls/DragControls.js +8 -33
- package/examples/js/controls/FirstPersonControls.js +32 -54
- package/examples/js/controls/FlyControls.js +29 -55
- package/examples/js/controls/OrbitControls.js +85 -95
- package/examples/js/controls/PointerLockControls.js +5 -14
- package/examples/js/controls/TrackballControls.js +33 -86
- package/examples/js/controls/TransformControls.js +84 -169
- package/examples/js/csm/CSM.js +4 -39
- package/examples/js/csm/CSMFrustum.js +3 -9
- package/examples/js/csm/CSMHelper.js +24 -4
- package/examples/js/csm/CSMShader.js +2 -6
- package/examples/js/curves/CurveExtras.js +27 -27
- package/examples/js/curves/NURBSCurve.js +4 -16
- package/examples/js/curves/NURBSSurface.js +3 -9
- package/examples/js/curves/NURBSUtils.js +8 -45
- package/examples/js/effects/AnaglyphEffect.js +4 -18
- package/examples/js/effects/AsciiEffect.js +32 -31
- package/examples/js/effects/OutlineEffect.js +26 -30
- package/examples/js/effects/ParallaxBarrierEffect.js +0 -13
- package/examples/js/effects/PeppersGhostEffect.js +12 -39
- package/examples/js/effects/StereoEffect.js +0 -4
- package/examples/js/environments/RoomEnvironment.js +12 -10
- package/examples/js/exporters/ColladaExporter.js +48 -65
- package/examples/js/exporters/DRACOExporter.js +22 -22
- package/examples/js/exporters/EXRExporter.js +15 -18
- package/examples/js/exporters/GLTFExporter.js +143 -261
- package/examples/js/exporters/MMDExporter.js +5 -12
- package/examples/js/exporters/OBJExporter.js +42 -33
- package/examples/js/exporters/PLYExporter.js +38 -33
- package/examples/js/exporters/STLExporter.js +5 -7
- package/examples/js/exporters/USDZExporter.js +110 -25
- package/examples/js/geometries/BoxLineGeometry.js +0 -1
- package/examples/js/geometries/ConvexGeometry.js +11 -6
- package/examples/js/geometries/DecalGeometry.js +53 -20
- package/examples/js/geometries/LightningStrike.js +54 -67
- package/examples/js/geometries/ParametricGeometries.js +8 -7
- package/examples/js/geometries/ParametricGeometry.js +25 -12
- package/examples/js/geometries/RoundedBoxGeometry.js +21 -19
- package/examples/js/geometries/TeapotGeometry.js +54 -50
- package/examples/js/geometries/TextGeometry.js +6 -4
- package/examples/js/helpers/LightProbeHelper.js +1 -2
- package/examples/js/helpers/OctreeHelper.js +22 -20
- package/examples/js/helpers/PositionalAudioHelper.js +8 -6
- package/examples/js/helpers/RectAreaLightHelper.js +6 -7
- package/examples/js/helpers/VertexNormalsHelper.js +15 -13
- package/examples/js/helpers/VertexTangentsHelper.js +15 -9
- package/examples/js/helpers/ViewHelper.js +31 -16
- package/examples/js/interactive/HTMLMesh.js +22 -33
- package/examples/js/interactive/InteractiveGroup.js +6 -12
- package/examples/js/interactive/SelectionBox.js +3 -70
- package/examples/js/interactive/SelectionHelper.js +0 -8
- package/examples/js/lights/LightProbeGenerator.js +32 -39
- package/examples/js/lights/RectAreaLightUniformsLib.js +5 -1
- package/examples/js/lines/LineGeometry.js +3 -5
- package/examples/js/lines/LineMaterial.js +4 -11
- package/examples/js/lines/LineSegments2.js +38 -89
- package/examples/js/lines/LineSegmentsGeometry.js +7 -28
- package/examples/js/lines/Wireframe.js +2 -7
- package/examples/js/lines/WireframeGeometry2.js +3 -1
- package/examples/js/loaders/3DMLoader.js +58 -155
- package/examples/js/loaders/3MFLoader.js +72 -106
- package/examples/js/loaders/AMFLoader.js +0 -25
- package/examples/js/loaders/BVHLoader.js +44 -43
- package/examples/js/loaders/BasisTextureLoader.js +16 -46
- package/examples/js/loaders/ColladaLoader.js +201 -359
- package/examples/js/loaders/DDSLoader.js +24 -25
- package/examples/js/loaders/DRACOLoader.js +29 -66
- package/examples/js/loaders/EXRLoader.js +67 -164
- package/examples/js/loaders/FBXLoader.js +286 -441
- package/examples/js/loaders/FontLoader.js +6 -15
- package/examples/js/loaders/GCodeLoader.js +15 -16
- package/examples/js/loaders/GLTFLoader.js +354 -405
- package/examples/js/loaders/HDRCubeTextureLoader.js +0 -6
- package/examples/js/loaders/KMZLoader.js +3 -7
- package/examples/js/loaders/KTXLoader.js +12 -30
- package/examples/js/loaders/LDrawLoader.js +178 -289
- package/examples/js/loaders/LUT3dlLoader.js +7 -11
- package/examples/js/loaders/LUTCubeLoader.js +0 -8
- package/examples/js/loaders/LWOLoader.js +59 -124
- package/examples/js/loaders/LogLuvLoader.js +27 -77
- package/examples/js/loaders/LottieLoader.js +4 -4
- package/examples/js/loaders/MD2Loader.js +26 -27
- package/examples/js/loaders/MDDLoader.js +6 -10
- package/examples/js/loaders/MMDLoader.js +180 -189
- package/examples/js/loaders/MTLLoader.js +18 -47
- package/examples/js/loaders/MaterialXLoader.js +392 -0
- package/examples/js/loaders/NRRDLoader.js +44 -84
- package/examples/js/loaders/OBJLoader.js +50 -65
- package/examples/js/loaders/PCDLoader.js +34 -29
- package/examples/js/loaders/PDBLoader.js +17 -13
- package/examples/js/loaders/PLYLoader.js +9 -39
- package/examples/js/loaders/PRWMLoader.js +11 -22
- package/examples/js/loaders/PVRLoader.js +7 -16
- package/examples/js/loaders/RGBELoader.js +36 -61
- package/examples/js/loaders/RGBMLoader.js +26 -87
- package/examples/js/loaders/STLLoader.js +20 -27
- package/examples/js/loaders/SVGLoader.js +361 -233
- package/examples/js/loaders/TDSLoader.js +81 -118
- package/examples/js/loaders/TGALoader.js +39 -41
- package/examples/js/loaders/TIFFLoader.js +0 -1
- package/examples/js/loaders/TTFLoader.js +0 -8
- package/examples/js/loaders/TiltLoader.js +14 -15
- package/examples/js/loaders/VOXLoader.js +8 -16
- package/examples/js/loaders/VRMLLoader.js +243 -340
- package/examples/js/loaders/VTKLoader.js +101 -118
- package/examples/js/loaders/XYZLoader.js +2 -4
- package/examples/js/loaders/lwo/IFFParser.js +55 -136
- package/examples/js/loaders/lwo/LWO2Parser.js +32 -83
- package/examples/js/loaders/lwo/LWO3Parser.js +31 -73
- package/examples/js/materials/MeshGouraudMaterial.js +15 -13
- package/examples/js/math/Capsule.js +0 -17
- package/examples/js/math/ColorConverter.js +3 -3
- package/examples/js/math/ConvexHull.js +183 -139
- package/examples/js/math/ImprovedNoise.js +1 -1
- package/examples/js/math/Lut.js +8 -15
- package/examples/js/math/MeshSurfaceSampler.js +6 -28
- package/examples/js/math/OBB.js +90 -49
- package/examples/js/math/Octree.js +2 -57
- package/examples/js/math/SimplexNoise.js +74 -88
- package/examples/js/misc/ConvexObjectBreaker.js +37 -48
- package/examples/js/misc/GPUComputationRenderer.js +14 -18
- package/examples/js/misc/Gyroscope.js +5 -9
- package/examples/js/misc/MD2Character.js +14 -23
- package/examples/js/misc/MD2CharacterComplex.js +73 -54
- package/examples/js/misc/MorphAnimMesh.js +0 -6
- package/examples/js/misc/MorphBlendMesh.js +3 -30
- package/examples/js/misc/ProgressiveLightMap.js +47 -43
- package/examples/js/misc/RollerCoaster.js +17 -24
- package/examples/js/misc/TubePainter.js +18 -12
- package/examples/js/misc/Volume.js +16 -45
- package/examples/js/misc/VolumeSlice.js +14 -24
- package/examples/js/modifiers/CurveModifier.js +19 -21
- package/examples/js/modifiers/EdgeSplitModifier.js +0 -30
- package/examples/js/modifiers/SimplifyModifier.js +56 -59
- package/examples/js/modifiers/TessellateModifier.js +2 -9
- package/examples/js/objects/GroundProjectedEnv.js +2 -14
- package/examples/js/objects/Lensflare.js +47 -38
- package/examples/js/objects/LightningStorm.js +10 -13
- package/examples/js/objects/MarchingCubes.js +80 -59
- package/examples/js/objects/Reflector.js +22 -20
- package/examples/js/objects/ReflectorForSSRPass.js +19 -23
- package/examples/js/objects/Refractor.js +52 -30
- package/examples/js/objects/ShadowMesh.js +1 -2
- package/examples/js/objects/Sky.js +2 -7
- package/examples/js/objects/Water.js +23 -18
- package/examples/js/objects/Water2.js +20 -19
- package/examples/js/physics/AmmoPhysics.js +23 -20
- package/examples/js/physics/OimoPhysics.js +19 -17
- package/examples/js/postprocessing/AdaptiveToneMappingPass.js +13 -20
- package/examples/js/postprocessing/AfterimagePass.js +19 -12
- package/examples/js/postprocessing/BloomPass.js +38 -17
- package/examples/js/postprocessing/BokehPass.js +29 -12
- package/examples/js/postprocessing/ClearPass.js +1 -6
- package/examples/js/postprocessing/CubeTexturePass.js +12 -9
- package/examples/js/postprocessing/DotScreenPass.js +7 -5
- package/examples/js/postprocessing/EffectComposer.js +25 -32
- package/examples/js/postprocessing/FilmPass.js +7 -5
- package/examples/js/postprocessing/GlitchPass.js +10 -11
- package/examples/js/postprocessing/HalftonePass.js +9 -9
- package/examples/js/postprocessing/LUTPass.js +2 -15
- package/examples/js/postprocessing/MaskPass.js +20 -17
- package/examples/js/postprocessing/OutlinePass.js +45 -36
- package/examples/js/postprocessing/Pass.js +11 -14
- package/examples/js/postprocessing/RenderPass.js +3 -7
- package/examples/js/postprocessing/SAOPass.js +40 -32
- package/examples/js/postprocessing/SMAAPass.js +34 -17
- package/examples/js/postprocessing/SSAARenderPass.js +14 -14
- package/examples/js/postprocessing/SSAOPass.js +56 -42
- package/examples/js/postprocessing/SSRPass.js +78 -61
- package/examples/js/postprocessing/SavePass.js +14 -6
- package/examples/js/postprocessing/ShaderPass.js +9 -8
- package/examples/js/postprocessing/TAARenderPass.js +11 -9
- package/examples/js/postprocessing/TexturePass.js +7 -4
- package/examples/js/postprocessing/UnrealBloomPass.js +43 -25
- package/examples/js/renderers/CSS2DRenderer.js +2 -21
- package/examples/js/renderers/CSS3DRenderer.js +3 -24
- package/examples/js/renderers/Projector.js +29 -85
- package/examples/js/renderers/SVGRenderer.js +4 -50
- package/examples/js/shaders/ACESFilmicToneMappingShader.js +3 -6
- package/examples/js/shaders/AfterimageShader.js +3 -6
- package/examples/js/shaders/BasicShader.js +3 -6
- package/examples/js/shaders/BleachBypassShader.js +3 -6
- package/examples/js/shaders/BlendShader.js +3 -6
- package/examples/js/shaders/BokehShader.js +3 -6
- package/examples/js/shaders/BokehShader2.js +4 -13
- package/examples/js/shaders/BrightnessContrastShader.js +3 -6
- package/examples/js/shaders/ColorCorrectionShader.js +2 -6
- package/examples/js/shaders/ColorifyShader.js +2 -6
- package/examples/js/shaders/ConvolutionShader.js +5 -10
- package/examples/js/shaders/CopyShader.js +3 -6
- package/examples/js/shaders/DOFMipMapShader.js +3 -6
- package/examples/js/shaders/DepthLimitedBlurShader.js +2 -9
- package/examples/js/shaders/DigitalGlitch.js +3 -6
- package/examples/js/shaders/DotScreenShader.js +2 -6
- package/examples/js/shaders/FXAAShader.js +1 -3
- package/examples/js/shaders/FilmShader.js +3 -6
- package/examples/js/shaders/FocusShader.js +3 -6
- package/examples/js/shaders/FreiChenShader.js +2 -6
- package/examples/js/shaders/GammaCorrectionShader.js +3 -6
- package/examples/js/shaders/GodRaysShader.js +11 -24
- package/examples/js/shaders/HalftoneShader.js +3 -6
- package/examples/js/shaders/HorizontalBlurShader.js +3 -6
- package/examples/js/shaders/HorizontalTiltShiftShader.js +3 -6
- package/examples/js/shaders/HueSaturationShader.js +3 -6
- package/examples/js/shaders/KaleidoShader.js +3 -6
- package/examples/js/shaders/LuminosityHighPassShader.js +2 -6
- package/examples/js/shaders/LuminosityShader.js +3 -6
- package/examples/js/shaders/MMDToonShader.js +2 -6
- package/examples/js/shaders/MirrorShader.js +3 -6
- package/examples/js/shaders/NormalMapShader.js +2 -6
- package/examples/js/shaders/RGBShiftShader.js +3 -6
- package/examples/js/shaders/SAOShader.js +2 -6
- package/examples/js/shaders/SMAAShader.js +6 -18
- package/examples/js/shaders/SSAOShader.js +2 -6
- package/examples/js/shaders/SSRShader.js +6 -18
- package/examples/js/shaders/SepiaShader.js +3 -6
- package/examples/js/shaders/SobelOperatorShader.js +2 -6
- package/examples/js/shaders/TechnicolorShader.js +3 -6
- package/examples/js/shaders/ToneMapShader.js +3 -6
- package/examples/js/shaders/ToonShader.js +8 -24
- package/examples/js/shaders/TriangleBlurShader.js +2 -6
- package/examples/js/shaders/UnpackDepthRGBAShader.js +3 -6
- package/examples/js/shaders/VelocityShader.js +126 -0
- package/examples/js/shaders/VerticalBlurShader.js +3 -6
- package/examples/js/shaders/VerticalTiltShiftShader.js +3 -6
- package/examples/js/shaders/VignetteShader.js +3 -6
- package/examples/js/shaders/VolumeShader.js +2 -6
- package/examples/js/shaders/WaterRefractionShader.js +2 -6
- package/examples/js/textures/FlakesTexture.js +0 -1
- package/examples/js/utils/BufferGeometryUtils.js +234 -168
- package/examples/js/utils/CameraUtils.js +5 -20
- package/examples/js/utils/GPUStatsPanel.js +3 -12
- package/examples/js/utils/GeometryCompressionUtils.js +19 -44
- package/examples/js/utils/GeometryUtils.js +13 -18
- package/examples/js/utils/LDrawUtils.js +8 -11
- package/examples/js/utils/PackedPhongMaterial.js +6 -4
- package/examples/js/utils/SceneUtils.js +117 -6
- package/examples/js/utils/ShadowMapViewer.js +17 -14
- package/examples/js/utils/SkeletonUtils.js +13 -27
- package/examples/js/utils/UVsDebug.js +20 -12
- package/examples/js/utils/WorkerPool.js +1 -11
- package/examples/jsm/animation/CCDIKSolver.js +1 -1
- package/examples/jsm/capabilities/WebGPU.js +3 -1
- package/examples/jsm/controls/OrbitControls.js +44 -4
- package/examples/jsm/exporters/GLTFExporter.js +17 -131
- package/examples/jsm/exporters/USDZExporter.js +75 -19
- package/examples/jsm/interactive/HTMLMesh.js +2 -0
- package/examples/jsm/libs/lottie_canvas.module.js +14844 -0
- package/examples/jsm/loaders/3DMLoader.js +1 -2
- package/examples/jsm/loaders/ColladaLoader.js +28 -0
- package/examples/jsm/loaders/FBXLoader.js +16 -2
- package/examples/jsm/loaders/GLTFLoader.js +204 -377
- package/examples/jsm/loaders/KTX2Loader.js +68 -29
- package/examples/jsm/loaders/LDrawLoader.js +14 -13
- package/examples/jsm/loaders/LottieLoader.js +4 -2
- package/examples/jsm/loaders/MaterialXLoader.js +728 -0
- package/examples/jsm/loaders/PCDLoader.js +1 -1
- package/examples/jsm/loaders/PLYLoader.js +68 -16
- package/examples/jsm/loaders/SVGLoader.js +227 -14
- package/examples/jsm/loaders/USDZLoader.js +31 -16
- package/examples/jsm/nodes/Nodes.js +14 -2
- package/examples/jsm/nodes/accessors/Object3DNode.js +1 -1
- package/examples/jsm/nodes/accessors/PositionNode.js +6 -0
- package/examples/jsm/nodes/accessors/ReferenceNode.js +1 -1
- package/examples/jsm/nodes/accessors/SkinningNode.js +1 -1
- package/examples/jsm/nodes/core/Node.js +1 -1
- package/examples/jsm/nodes/core/NodeBuilder.js +36 -4
- package/examples/jsm/nodes/core/NodeFrame.js +2 -2
- package/examples/jsm/nodes/core/NodeVarying.js +7 -4
- package/examples/jsm/nodes/core/VaryingNode.js +6 -4
- package/examples/jsm/nodes/core/constants.js +13 -13
- package/examples/jsm/nodes/display/PosterizeNode.js +25 -0
- package/examples/jsm/nodes/display/ViewportNode.js +106 -0
- package/examples/jsm/nodes/gpgpu/ComputeNode.js +1 -1
- package/examples/jsm/nodes/lighting/AnalyticLightNode.js +1 -1
- package/examples/jsm/nodes/loaders/NodeMaterialLoader.js +3 -1
- package/examples/jsm/nodes/materials/Materials.js +9 -7
- package/examples/jsm/nodes/materials/NodeMaterial.js +9 -1
- package/examples/jsm/nodes/materialx/MaterialXNodes.js +6 -2
- package/examples/jsm/nodes/materialx/lib/mx_transform_color.js +18 -0
- package/examples/jsm/nodes/math/MathNode.js +5 -0
- package/examples/jsm/nodes/math/OperatorNode.js +6 -1
- package/examples/jsm/nodes/shadernode/ShaderNode.js +26 -13
- package/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js +2 -0
- package/examples/jsm/nodes/shadernode/ShaderNodeElements.js +18 -0
- package/examples/jsm/nodes/utils/EquirectUVNode.js +27 -0
- package/examples/jsm/nodes/utils/JoinNode.js +8 -2
- package/examples/jsm/nodes/utils/MatcapUVNode.js +2 -4
- package/examples/jsm/nodes/utils/MaxMipLevelNode.js +1 -1
- package/examples/jsm/nodes/utils/SpriteSheetUVNode.js +8 -10
- package/examples/jsm/nodes/utils/TimerNode.js +1 -1
- package/examples/jsm/nodes/utils/TriplanarTexturesNode.js +51 -0
- package/examples/jsm/postprocessing/AfterimagePass.js +17 -4
- package/examples/jsm/postprocessing/BloomPass.js +22 -3
- package/examples/jsm/postprocessing/BokehPass.js +18 -4
- package/examples/jsm/postprocessing/CubeTexturePass.js +12 -5
- package/examples/jsm/postprocessing/DotScreenPass.js +8 -0
- package/examples/jsm/postprocessing/EffectComposer.js +9 -0
- package/examples/jsm/postprocessing/FilmPass.js +8 -0
- package/examples/jsm/postprocessing/GlitchPass.js +13 -1
- package/examples/jsm/postprocessing/HalftonePass.js +8 -0
- package/examples/jsm/postprocessing/OutlinePass.js +10 -0
- package/examples/jsm/postprocessing/Pass.js +2 -0
- package/examples/jsm/postprocessing/RenderPixelatedPass.js +234 -0
- package/examples/jsm/postprocessing/SAOPass.js +20 -0
- package/examples/jsm/postprocessing/SMAAPass.js +16 -0
- package/examples/jsm/postprocessing/SSAARenderPass.js +4 -0
- package/examples/jsm/postprocessing/SavePass.js +17 -1
- package/examples/jsm/postprocessing/ShaderPass.js +8 -0
- package/examples/jsm/postprocessing/TAARenderPass.js +9 -0
- package/examples/jsm/postprocessing/TexturePass.js +8 -0
- package/examples/jsm/postprocessing/UnrealBloomPass.js +16 -0
- package/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js +39 -16
- package/examples/jsm/renderers/webgpu/WebGPUAnimation.js +58 -0
- package/examples/jsm/renderers/webgpu/WebGPUAttributes.js +63 -5
- package/examples/jsm/renderers/webgpu/WebGPUBackground.js +36 -7
- package/examples/jsm/renderers/webgpu/WebGPURenderer.js +47 -12
- package/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js +35 -5
- package/examples/jsm/shaders/MMDToonShader.js +0 -2
- package/examples/jsm/shaders/VelocityShader.js +128 -0
- package/examples/jsm/utils/BufferGeometryUtils.js +130 -6
- package/examples/jsm/utils/SceneUtils.js +129 -4
- package/examples/jsm/utils/TextureUtils.js +85 -0
- package/examples/jsm/webxr/OculusHandModel.js +1 -1
- package/examples/jsm/webxr/XRHandMeshModel.js +6 -3
- package/package.json +11 -12
- package/src/Three.js +1 -0
- package/src/audio/AudioContext.js +5 -5
- package/src/cameras/CubeCamera.js +14 -14
- package/src/constants.js +1 -1
- package/src/core/InstancedBufferGeometry.js +1 -7
- package/src/extras/Earcut.js +67 -67
- package/src/helpers/DirectionalLightHelper.js +5 -1
- package/src/helpers/HemisphereLightHelper.js +4 -1
- package/src/helpers/PointLightHelper.js +2 -1
- package/src/helpers/SpotLightHelper.js +4 -2
- package/src/lights/PointLight.js +2 -2
- package/src/lights/SpotLight.js +2 -2
- package/src/loaders/FileLoader.js +4 -1
- package/src/loaders/ObjectLoader.js +5 -1
- package/src/materials/Material.js +1 -1
- package/src/math/Color.js +5 -5
- package/src/math/Matrix3.js +53 -18
- package/src/math/Ray.js +2 -5
- package/src/math/Sphere.js +19 -26
- package/src/objects/InstancedMesh.js +7 -0
- package/src/objects/LOD.js +25 -6
- package/src/renderers/WebGL3DRenderTarget.js +1 -1
- package/src/renderers/WebGLArrayRenderTarget.js +1 -1
- package/src/renderers/WebGLCubeRenderTarget.js +1 -1
- package/src/renderers/WebGLMultipleRenderTargets.js +1 -1
- package/src/renderers/WebGLRenderTarget.js +1 -1
- package/src/renderers/WebGLRenderer.js +36 -62
- package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +0 -4
- package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +0 -1
- package/src/renderers/shaders/ShaderChunk/lights_lambert_pars_fragment.glsl.js +0 -2
- package/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl.js +0 -2
- package/src/renderers/shaders/ShaderChunk/lights_toon_pars_fragment.glsl.js +0 -2
- package/src/renderers/shaders/ShaderChunk/packing.glsl.js +8 -0
- package/src/renderers/shaders/ShaderChunk.js +3 -0
- package/src/renderers/shaders/ShaderLib/background.glsl.js +7 -2
- package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +62 -0
- package/src/renderers/shaders/ShaderLib/cube.glsl.js +4 -6
- package/src/renderers/shaders/ShaderLib.js +20 -6
- package/src/renderers/shaders/UniformsLib.js +1 -1
- package/src/renderers/shaders/UniformsUtils.js +15 -0
- package/src/renderers/webgl/WebGLAttributes.js +2 -0
- package/src/renderers/webgl/WebGLBackground.js +15 -7
- package/src/renderers/webgl/WebGLLights.js +0 -4
- package/src/renderers/webgl/WebGLMaterials.js +2 -1
- package/src/renderers/webgl/WebGLShadowMap.js +3 -1
- package/src/renderers/webgl/WebGLState.js +31 -1
- package/src/renderers/webgl/WebGLTextures.js +71 -18
- package/src/renderers/webgl/WebGLUniforms.js +116 -20
- package/src/renderers/webgl/WebGLUtils.js +1 -1
- package/src/renderers/webxr/WebXRController.js +46 -13
- package/src/renderers/webxr/WebXRManager.js +85 -3
- package/src/scenes/Scene.js +8 -0
- package/src/textures/CompressedArrayTexture.js +18 -0
- package/examples/js/libs/lottie_canvas.js +0 -12751
- package/examples/js/shaders/PixelShader.js +0 -51
- package/examples/jsm/shaders/PixelShader.js +0 -44
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
constructor( manager ) {
|
|
6
6
|
|
|
7
|
-
super( manager );
|
|
7
|
+
super( manager );
|
|
8
8
|
|
|
9
|
-
|
|
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
|
-
|
|
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' );
|
|
179
|
+
const d = node.getAttribute( 'd' );
|
|
197
180
|
|
|
198
|
-
|
|
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
|
-
}
|
|
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;
|
|
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 );
|
|
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;
|
|
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;
|
|
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;
|
|
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;
|
|
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' ) );
|
|
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();
|
|
617
|
+
const path = new THREE.ShapePath();
|
|
673
618
|
|
|
674
|
-
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
};
|
|
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 ];
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
1121
|
-
|
|
1062
|
+
}
|
|
1122
1063
|
|
|
1064
|
+
// add the last number found (if any)
|
|
1123
1065
|
newNumber();
|
|
1124
1066
|
return result;
|
|
1125
1067
|
|
|
1126
|
-
}
|
|
1068
|
+
}
|
|
1127
1069
|
|
|
1070
|
+
// Units
|
|
1128
1071
|
|
|
1129
|
-
const units = [ 'mm', 'cm', 'in', 'pt', 'pc', 'px' ];
|
|
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
|
-
}
|
|
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;
|
|
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
|
-
}
|
|
1312
|
-
|
|
1246
|
+
}
|
|
1313
1247
|
|
|
1314
|
-
|
|
1315
|
-
|
|
1248
|
+
// Rotate around center (cx, cy)
|
|
1249
|
+
tempTransform1.makeTranslation( - cx, - cy );
|
|
1250
|
+
tempTransform2.makeRotation( angle );
|
|
1316
1251
|
tempTransform3.multiplyMatrices( tempTransform2, tempTransform1 );
|
|
1317
|
-
tempTransform1.
|
|
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
|
-
|
|
1393
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1435
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
};
|
|
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 );
|
|
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;
|
|
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
|
-
}
|
|
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;
|
|
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 );
|
|
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;
|
|
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;
|
|
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 ];
|
|
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
|
-
}
|
|
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 ) );
|
|
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 );
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
}
|
|
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;
|
|
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 );
|
|
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 );
|
|
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 );
|
|
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;
|
|
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 ) {
|