@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
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
( function () {
|
|
2
2
|
|
|
3
|
+
// Special surface finish tag types.
|
|
3
4
|
// Note: "MATERIAL" tag (e.g. GLITTER, SPECKLE) is not implemented
|
|
4
|
-
|
|
5
5
|
const FINISH_TYPE_DEFAULT = 0;
|
|
6
6
|
const FINISH_TYPE_CHROME = 1;
|
|
7
7
|
const FINISH_TYPE_PEARLESCENT = 2;
|
|
8
8
|
const FINISH_TYPE_RUBBER = 3;
|
|
9
9
|
const FINISH_TYPE_MATTE_METALLIC = 4;
|
|
10
|
-
const FINISH_TYPE_METAL = 5;
|
|
11
|
-
// The LDraw standard establishes these various possible subfolders.
|
|
10
|
+
const FINISH_TYPE_METAL = 5;
|
|
12
11
|
|
|
12
|
+
// State machine to search a subobject path.
|
|
13
|
+
// The LDraw standard establishes these various possible subfolders.
|
|
13
14
|
const FILE_LOCATION_TRY_PARTS = 0;
|
|
14
15
|
const FILE_LOCATION_TRY_P = 1;
|
|
15
16
|
const FILE_LOCATION_TRY_MODELS = 2;
|
|
@@ -19,11 +20,8 @@
|
|
|
19
20
|
const FILE_LOCATION_NOT_FOUND = 6;
|
|
20
21
|
const MAIN_COLOUR_CODE = '16';
|
|
21
22
|
const MAIN_EDGE_COLOUR_CODE = '24';
|
|
22
|
-
|
|
23
23
|
const _tempVec0 = new THREE.Vector3();
|
|
24
|
-
|
|
25
24
|
const _tempVec1 = new THREE.Vector3();
|
|
26
|
-
|
|
27
25
|
class LDrawConditionalLineMaterial extends THREE.ShaderMaterial {
|
|
28
26
|
|
|
29
27
|
constructor( parameters ) {
|
|
@@ -37,9 +35,7 @@
|
|
|
37
35
|
value: 1.0
|
|
38
36
|
}
|
|
39
37
|
} ] ),
|
|
40
|
-
vertexShader:
|
|
41
|
-
/* glsl */
|
|
42
|
-
`
|
|
38
|
+
vertexShader: /* glsl */`
|
|
43
39
|
attribute vec3 control0;
|
|
44
40
|
attribute vec3 control1;
|
|
45
41
|
attribute vec3 direction;
|
|
@@ -86,9 +82,7 @@
|
|
|
86
82
|
#include <fog_vertex>
|
|
87
83
|
}
|
|
88
84
|
`,
|
|
89
|
-
fragmentShader:
|
|
90
|
-
/* glsl */
|
|
91
|
-
`
|
|
85
|
+
fragmentShader: /* glsl */`
|
|
92
86
|
uniform vec3 diffuse;
|
|
93
87
|
uniform float opacity;
|
|
94
88
|
varying float discardFlag;
|
|
@@ -143,7 +137,6 @@
|
|
|
143
137
|
}
|
|
144
138
|
|
|
145
139
|
}
|
|
146
|
-
|
|
147
140
|
class ConditionalLineSegments extends THREE.LineSegments {
|
|
148
141
|
|
|
149
142
|
constructor( geometry, material ) {
|
|
@@ -154,7 +147,6 @@
|
|
|
154
147
|
}
|
|
155
148
|
|
|
156
149
|
}
|
|
157
|
-
|
|
158
150
|
function generateFaceNormals( faces ) {
|
|
159
151
|
|
|
160
152
|
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
@@ -164,11 +156,8 @@
|
|
|
164
156
|
const v0 = vertices[ 0 ];
|
|
165
157
|
const v1 = vertices[ 1 ];
|
|
166
158
|
const v2 = vertices[ 2 ];
|
|
167
|
-
|
|
168
159
|
_tempVec0.subVectors( v1, v0 );
|
|
169
|
-
|
|
170
160
|
_tempVec1.subVectors( v2, v1 );
|
|
171
|
-
|
|
172
161
|
face.faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize();
|
|
173
162
|
|
|
174
163
|
}
|
|
@@ -176,7 +165,6 @@
|
|
|
176
165
|
}
|
|
177
166
|
|
|
178
167
|
const _ray = new THREE.Ray();
|
|
179
|
-
|
|
180
168
|
function smoothNormals( faces, lineSegments, checkSubSegments = false ) {
|
|
181
169
|
|
|
182
170
|
// NOTE: 1e2 is pretty coarse but was chosen to quantize the resulting value because
|
|
@@ -187,8 +175,8 @@
|
|
|
187
175
|
// vertices that should be merged might be set to "1.7" and "1.6999..." meaning they won't
|
|
188
176
|
// get merged. This added epsilon attempts to push these error values to the same quantized
|
|
189
177
|
// value for the sake of hashing. See "AT-ST mini" dishes. See mrdoob/three#23169.
|
|
190
|
-
const hashMultiplier = ( 1 + 1e-10 ) * 1e2;
|
|
191
178
|
|
|
179
|
+
const hashMultiplier = ( 1 + 1e-10 ) * 1e2;
|
|
192
180
|
function hashVertex( v ) {
|
|
193
181
|
|
|
194
182
|
const x = ~ ~ ( v.x * hashMultiplier );
|
|
@@ -202,10 +190,10 @@
|
|
|
202
190
|
|
|
203
191
|
return `${hashVertex( v0 )}_${hashVertex( v1 )}`;
|
|
204
192
|
|
|
205
|
-
}
|
|
206
|
-
// onto the original line.
|
|
207
|
-
|
|
193
|
+
}
|
|
208
194
|
|
|
195
|
+
// converts the two vertices to a ray with a normalized direction and origin of 0, 0, 0 projected
|
|
196
|
+
// onto the original line.
|
|
209
197
|
function toNormalizedRay( v0, v1, targetRay ) {
|
|
210
198
|
|
|
211
199
|
targetRay.direction.subVectors( v1, v0 ).normalize();
|
|
@@ -224,8 +212,9 @@
|
|
|
224
212
|
const hardEdges = new Set();
|
|
225
213
|
const hardEdgeRays = new Map();
|
|
226
214
|
const halfEdgeList = {};
|
|
227
|
-
const normals = [];
|
|
215
|
+
const normals = [];
|
|
228
216
|
|
|
217
|
+
// Save the list of hard edges by hash
|
|
229
218
|
for ( let i = 0, l = lineSegments.length; i < l; i ++ ) {
|
|
230
219
|
|
|
231
220
|
const ls = lineSegments[ i ];
|
|
@@ -233,15 +222,15 @@
|
|
|
233
222
|
const v0 = vertices[ 0 ];
|
|
234
223
|
const v1 = vertices[ 1 ];
|
|
235
224
|
hardEdges.add( hashEdge( v0, v1 ) );
|
|
236
|
-
hardEdges.add( hashEdge( v1, v0 ) );
|
|
237
|
-
// and requires more memory.
|
|
225
|
+
hardEdges.add( hashEdge( v1, v0 ) );
|
|
238
226
|
|
|
227
|
+
// only generate the hard edge ray map if we're checking subsegments because it's more expensive to check
|
|
228
|
+
// and requires more memory.
|
|
239
229
|
if ( checkSubSegments ) {
|
|
240
230
|
|
|
241
231
|
// add both ray directions to the map
|
|
242
232
|
const ray = toNormalizedRay( v0, v1, new THREE.Ray() );
|
|
243
233
|
const rh1 = hashRay( ray );
|
|
244
|
-
|
|
245
234
|
if ( ! hardEdgeRays.has( rh1 ) ) {
|
|
246
235
|
|
|
247
236
|
toNormalizedRay( v1, v0, ray );
|
|
@@ -253,14 +242,13 @@
|
|
|
253
242
|
hardEdgeRays.set( rh1, info );
|
|
254
243
|
hardEdgeRays.set( rh2, info );
|
|
255
244
|
|
|
256
|
-
}
|
|
257
|
-
// subsegment later.
|
|
258
|
-
|
|
245
|
+
}
|
|
259
246
|
|
|
247
|
+
// store both segments ends in min, max order in the distances array to check if a face edge is a
|
|
248
|
+
// subsegment later.
|
|
260
249
|
const info = hardEdgeRays.get( rh1 );
|
|
261
250
|
let d0 = info.ray.direction.dot( v0 );
|
|
262
251
|
let d1 = info.ray.direction.dot( v1 );
|
|
263
|
-
|
|
264
252
|
if ( d0 > d1 ) {
|
|
265
253
|
|
|
266
254
|
[ d0, d1 ] = [ d1, d0 ];
|
|
@@ -271,35 +259,34 @@
|
|
|
271
259
|
|
|
272
260
|
}
|
|
273
261
|
|
|
274
|
-
}
|
|
275
|
-
|
|
262
|
+
}
|
|
276
263
|
|
|
264
|
+
// track the half edges associated with each triangle
|
|
277
265
|
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
278
266
|
|
|
279
267
|
const tri = faces[ i ];
|
|
280
268
|
const vertices = tri.vertices;
|
|
281
269
|
const vertCount = vertices.length;
|
|
282
|
-
|
|
283
270
|
for ( let i2 = 0; i2 < vertCount; i2 ++ ) {
|
|
284
271
|
|
|
285
272
|
const index = i2;
|
|
286
273
|
const next = ( i2 + 1 ) % vertCount;
|
|
287
274
|
const v0 = vertices[ index ];
|
|
288
275
|
const v1 = vertices[ next ];
|
|
289
|
-
const hash = hashEdge( v0, v1 );
|
|
276
|
+
const hash = hashEdge( v0, v1 );
|
|
290
277
|
|
|
278
|
+
// don't add the triangle if the edge is supposed to be hard
|
|
291
279
|
if ( hardEdges.has( hash ) ) {
|
|
292
280
|
|
|
293
281
|
continue;
|
|
294
282
|
|
|
295
|
-
}
|
|
296
|
-
|
|
283
|
+
}
|
|
297
284
|
|
|
285
|
+
// if checking subsegments then check to see if this edge lies on a hard edge ray and whether its within any ray bounds
|
|
298
286
|
if ( checkSubSegments ) {
|
|
299
287
|
|
|
300
288
|
toNormalizedRay( v0, v1, _ray );
|
|
301
289
|
const rayHash = hashRay( _ray );
|
|
302
|
-
|
|
303
290
|
if ( hardEdgeRays.has( rayHash ) ) {
|
|
304
291
|
|
|
305
292
|
const info = hardEdgeRays.get( rayHash );
|
|
@@ -309,16 +296,14 @@
|
|
|
309
296
|
} = info;
|
|
310
297
|
let d0 = ray.direction.dot( v0 );
|
|
311
298
|
let d1 = ray.direction.dot( v1 );
|
|
312
|
-
|
|
313
299
|
if ( d0 > d1 ) {
|
|
314
300
|
|
|
315
301
|
[ d0, d1 ] = [ d1, d0 ];
|
|
316
302
|
|
|
317
|
-
}
|
|
318
|
-
|
|
303
|
+
}
|
|
319
304
|
|
|
305
|
+
// return early if the face edge is found to be a subsegment of a line edge meaning the edge will have "hard" normals
|
|
320
306
|
let found = false;
|
|
321
|
-
|
|
322
307
|
for ( let i = 0, l = distances.length; i < l; i += 2 ) {
|
|
323
308
|
|
|
324
309
|
if ( d0 >= distances[ i ] && d1 <= distances[ i + 1 ] ) {
|
|
@@ -348,14 +333,13 @@
|
|
|
348
333
|
|
|
349
334
|
}
|
|
350
335
|
|
|
351
|
-
}
|
|
352
|
-
|
|
336
|
+
}
|
|
353
337
|
|
|
338
|
+
// Iterate until we've tried to connect all faces to share normals
|
|
354
339
|
while ( true ) {
|
|
355
340
|
|
|
356
341
|
// Stop if there are no more faces left
|
|
357
342
|
let halfEdge = null;
|
|
358
|
-
|
|
359
343
|
for ( const key in halfEdgeList ) {
|
|
360
344
|
|
|
361
345
|
halfEdge = halfEdgeList[ key ];
|
|
@@ -367,62 +351,61 @@
|
|
|
367
351
|
|
|
368
352
|
break;
|
|
369
353
|
|
|
370
|
-
}
|
|
371
|
-
|
|
354
|
+
}
|
|
372
355
|
|
|
356
|
+
// Exhaustively find all connected faces
|
|
373
357
|
const queue = [ halfEdge ];
|
|
374
|
-
|
|
375
358
|
while ( queue.length > 0 ) {
|
|
376
359
|
|
|
377
360
|
// initialize all vertex normals in this triangle
|
|
378
361
|
const tri = queue.pop().tri;
|
|
379
362
|
const vertices = tri.vertices;
|
|
380
363
|
const vertNormals = tri.normals;
|
|
381
|
-
const faceNormal = tri.faceNormal;
|
|
364
|
+
const faceNormal = tri.faceNormal;
|
|
382
365
|
|
|
366
|
+
// Check if any edge is connected to another triangle edge
|
|
383
367
|
const vertCount = vertices.length;
|
|
384
|
-
|
|
385
368
|
for ( let i2 = 0; i2 < vertCount; i2 ++ ) {
|
|
386
369
|
|
|
387
370
|
const index = i2;
|
|
388
371
|
const next = ( i2 + 1 ) % vertCount;
|
|
389
372
|
const v0 = vertices[ index ];
|
|
390
|
-
const v1 = vertices[ next ];
|
|
373
|
+
const v1 = vertices[ next ];
|
|
391
374
|
|
|
375
|
+
// delete this triangle from the list so it won't be found again
|
|
392
376
|
const hash = hashEdge( v0, v1 );
|
|
393
377
|
delete halfEdgeList[ hash ];
|
|
394
378
|
const reverseHash = hashEdge( v1, v0 );
|
|
395
379
|
const otherInfo = halfEdgeList[ reverseHash ];
|
|
396
|
-
|
|
397
380
|
if ( otherInfo ) {
|
|
398
381
|
|
|
399
382
|
const otherTri = otherInfo.tri;
|
|
400
383
|
const otherIndex = otherInfo.index;
|
|
401
384
|
const otherNormals = otherTri.normals;
|
|
402
385
|
const otherVertCount = otherNormals.length;
|
|
403
|
-
const otherFaceNormal = otherTri.faceNormal;
|
|
386
|
+
const otherFaceNormal = otherTri.faceNormal;
|
|
387
|
+
|
|
388
|
+
// NOTE: If the angle between faces is > 67.5 degrees then assume it's
|
|
404
389
|
// hard edge. There are some cases where the line segments do not line up exactly
|
|
405
390
|
// with or span multiple triangle edges (see Lunar Vehicle wheels).
|
|
406
|
-
|
|
407
391
|
if ( Math.abs( otherTri.faceNormal.dot( tri.faceNormal ) ) < 0.25 ) {
|
|
408
392
|
|
|
409
393
|
continue;
|
|
410
394
|
|
|
411
|
-
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// if this triangle has already been traversed then it won't be in
|
|
412
398
|
// the halfEdgeList. If it has not then add it to the queue and delete
|
|
413
399
|
// it so it won't be found again.
|
|
414
|
-
|
|
415
|
-
|
|
416
400
|
if ( reverseHash in halfEdgeList ) {
|
|
417
401
|
|
|
418
402
|
queue.push( otherInfo );
|
|
419
403
|
delete halfEdgeList[ reverseHash ];
|
|
420
404
|
|
|
421
|
-
}
|
|
422
|
-
|
|
405
|
+
}
|
|
423
406
|
|
|
407
|
+
// share the first normal
|
|
424
408
|
const otherNext = ( otherIndex + 1 ) % otherVertCount;
|
|
425
|
-
|
|
426
409
|
if ( vertNormals[ index ] && otherNormals[ otherNext ] && vertNormals[ index ] !== otherNormals[ otherNext ] ) {
|
|
427
410
|
|
|
428
411
|
otherNormals[ otherNext ].norm.add( vertNormals[ index ].norm );
|
|
@@ -431,7 +414,6 @@
|
|
|
431
414
|
}
|
|
432
415
|
|
|
433
416
|
let sharedNormal1 = vertNormals[ index ] || otherNormals[ otherNext ];
|
|
434
|
-
|
|
435
417
|
if ( sharedNormal1 === null ) {
|
|
436
418
|
|
|
437
419
|
// it's possible to encounter an edge of a triangle that has already been traversed meaning
|
|
@@ -456,9 +438,9 @@
|
|
|
456
438
|
otherNormals[ otherNext ] = sharedNormal1;
|
|
457
439
|
sharedNormal1.norm.add( otherFaceNormal );
|
|
458
440
|
|
|
459
|
-
}
|
|
460
|
-
|
|
441
|
+
}
|
|
461
442
|
|
|
443
|
+
// share the second normal
|
|
462
444
|
if ( vertNormals[ next ] && otherNormals[ otherIndex ] && vertNormals[ next ] !== otherNormals[ otherIndex ] ) {
|
|
463
445
|
|
|
464
446
|
otherNormals[ otherIndex ].norm.add( vertNormals[ next ].norm );
|
|
@@ -467,7 +449,6 @@
|
|
|
467
449
|
}
|
|
468
450
|
|
|
469
451
|
let sharedNormal2 = vertNormals[ next ] || otherNormals[ otherIndex ];
|
|
470
|
-
|
|
471
452
|
if ( sharedNormal2 === null ) {
|
|
472
453
|
|
|
473
454
|
sharedNormal2 = {
|
|
@@ -497,9 +478,9 @@
|
|
|
497
478
|
|
|
498
479
|
}
|
|
499
480
|
|
|
500
|
-
}
|
|
501
|
-
|
|
481
|
+
}
|
|
502
482
|
|
|
483
|
+
// The normals of each face have been added up so now we average them by normalizing the vector.
|
|
503
484
|
for ( let i = 0, l = normals.length; i < l; i ++ ) {
|
|
504
485
|
|
|
505
486
|
normals[ i ].normalize();
|
|
@@ -531,13 +512,11 @@
|
|
|
531
512
|
this.lineNumber = lineNumber;
|
|
532
513
|
|
|
533
514
|
}
|
|
534
|
-
|
|
535
515
|
seekNonSpace() {
|
|
536
516
|
|
|
537
517
|
while ( this.currentCharIndex < this.lineLength ) {
|
|
538
518
|
|
|
539
519
|
this.currentChar = this.line.charAt( this.currentCharIndex );
|
|
540
|
-
|
|
541
520
|
if ( this.currentChar !== ' ' && this.currentChar !== '\t' ) {
|
|
542
521
|
|
|
543
522
|
return;
|
|
@@ -549,15 +528,14 @@
|
|
|
549
528
|
}
|
|
550
529
|
|
|
551
530
|
}
|
|
552
|
-
|
|
553
531
|
getToken() {
|
|
554
532
|
|
|
555
|
-
const pos0 = this.currentCharIndex ++;
|
|
533
|
+
const pos0 = this.currentCharIndex ++;
|
|
556
534
|
|
|
535
|
+
// Seek space
|
|
557
536
|
while ( this.currentCharIndex < this.lineLength ) {
|
|
558
537
|
|
|
559
538
|
this.currentChar = this.line.charAt( this.currentCharIndex );
|
|
560
|
-
|
|
561
539
|
if ( this.currentChar === ' ' || this.currentChar === '\t' ) {
|
|
562
540
|
|
|
563
541
|
break;
|
|
@@ -573,40 +551,35 @@
|
|
|
573
551
|
return this.line.substring( pos0, pos1 );
|
|
574
552
|
|
|
575
553
|
}
|
|
576
|
-
|
|
577
554
|
getVector() {
|
|
578
555
|
|
|
579
556
|
return new THREE.Vector3( parseFloat( this.getToken() ), parseFloat( this.getToken() ), parseFloat( this.getToken() ) );
|
|
580
557
|
|
|
581
558
|
}
|
|
582
|
-
|
|
583
559
|
getRemainingString() {
|
|
584
560
|
|
|
585
561
|
return this.line.substring( this.currentCharIndex, this.lineLength );
|
|
586
562
|
|
|
587
563
|
}
|
|
588
|
-
|
|
589
564
|
isAtTheEnd() {
|
|
590
565
|
|
|
591
566
|
return this.currentCharIndex >= this.lineLength;
|
|
592
567
|
|
|
593
568
|
}
|
|
594
|
-
|
|
595
569
|
setToEnd() {
|
|
596
570
|
|
|
597
571
|
this.currentCharIndex = this.lineLength;
|
|
598
572
|
|
|
599
573
|
}
|
|
600
|
-
|
|
601
574
|
getLineNumberString() {
|
|
602
575
|
|
|
603
576
|
return this.lineNumber >= 0 ? ' at line ' + this.lineNumber : '';
|
|
604
577
|
|
|
605
578
|
}
|
|
606
579
|
|
|
607
|
-
}
|
|
608
|
-
|
|
580
|
+
}
|
|
609
581
|
|
|
582
|
+
// Fetches and parses an intermediate representation of LDraw parts files.
|
|
610
583
|
class LDrawParsedCache {
|
|
611
584
|
|
|
612
585
|
constructor( loader ) {
|
|
@@ -615,12 +588,12 @@
|
|
|
615
588
|
this._cache = {};
|
|
616
589
|
|
|
617
590
|
}
|
|
618
|
-
|
|
619
591
|
cloneResult( original ) {
|
|
620
592
|
|
|
621
|
-
const result = {};
|
|
622
|
-
// so these pieces must be cloned.
|
|
593
|
+
const result = {};
|
|
623
594
|
|
|
595
|
+
// vertices are transformed and normals computed before being converted to geometry
|
|
596
|
+
// so these pieces must be cloned.
|
|
624
597
|
result.faces = original.faces.map( face => {
|
|
625
598
|
|
|
626
599
|
return {
|
|
@@ -650,8 +623,9 @@
|
|
|
650
623
|
vertices: face.vertices.map( v => v.clone() )
|
|
651
624
|
};
|
|
652
625
|
|
|
653
|
-
} );
|
|
626
|
+
} );
|
|
654
627
|
|
|
628
|
+
// none if this is subsequently modified
|
|
655
629
|
result.type = original.type;
|
|
656
630
|
result.category = original.category;
|
|
657
631
|
result.keywords = original.keywords;
|
|
@@ -659,48 +633,40 @@
|
|
|
659
633
|
result.subobjects = original.subobjects;
|
|
660
634
|
result.fileName = original.fileName;
|
|
661
635
|
result.totalFaces = original.totalFaces;
|
|
662
|
-
result.
|
|
636
|
+
result.startingBuildingStep = original.startingBuildingStep;
|
|
663
637
|
result.materials = original.materials;
|
|
664
638
|
result.group = null;
|
|
665
639
|
return result;
|
|
666
640
|
|
|
667
641
|
}
|
|
668
|
-
|
|
669
642
|
async fetchData( fileName ) {
|
|
670
643
|
|
|
671
644
|
let triedLowerCase = false;
|
|
672
645
|
let locationState = FILE_LOCATION_TRY_PARTS;
|
|
673
|
-
|
|
674
646
|
while ( locationState !== FILE_LOCATION_NOT_FOUND ) {
|
|
675
647
|
|
|
676
648
|
let subobjectURL = fileName;
|
|
677
|
-
|
|
678
649
|
switch ( locationState ) {
|
|
679
650
|
|
|
680
651
|
case FILE_LOCATION_AS_IS:
|
|
681
652
|
locationState = locationState + 1;
|
|
682
653
|
break;
|
|
683
|
-
|
|
684
654
|
case FILE_LOCATION_TRY_PARTS:
|
|
685
655
|
subobjectURL = 'parts/' + subobjectURL;
|
|
686
656
|
locationState = locationState + 1;
|
|
687
657
|
break;
|
|
688
|
-
|
|
689
658
|
case FILE_LOCATION_TRY_P:
|
|
690
659
|
subobjectURL = 'p/' + subobjectURL;
|
|
691
660
|
locationState = locationState + 1;
|
|
692
661
|
break;
|
|
693
|
-
|
|
694
662
|
case FILE_LOCATION_TRY_MODELS:
|
|
695
663
|
subobjectURL = 'models/' + subobjectURL;
|
|
696
664
|
locationState = locationState + 1;
|
|
697
665
|
break;
|
|
698
|
-
|
|
699
666
|
case FILE_LOCATION_TRY_RELATIVE:
|
|
700
667
|
subobjectURL = fileName.substring( 0, fileName.lastIndexOf( '/' ) + 1 ) + subobjectURL;
|
|
701
668
|
locationState = locationState + 1;
|
|
702
669
|
break;
|
|
703
|
-
|
|
704
670
|
case FILE_LOCATION_TRY_ABSOLUTE:
|
|
705
671
|
if ( triedLowerCase ) {
|
|
706
672
|
|
|
@@ -726,7 +692,6 @@
|
|
|
726
692
|
fileLoader.setPath( loader.partsLibraryPath );
|
|
727
693
|
fileLoader.setRequestHeader( loader.requestHeader );
|
|
728
694
|
fileLoader.setWithCredentials( loader.withCredentials );
|
|
729
|
-
|
|
730
695
|
try {
|
|
731
696
|
|
|
732
697
|
const text = await fileLoader.loadAsync( subobjectURL );
|
|
@@ -743,17 +708,16 @@
|
|
|
743
708
|
throw new Error( 'LDrawLoader: Subobject "' + fileName + '" could not be loaded.' );
|
|
744
709
|
|
|
745
710
|
}
|
|
746
|
-
|
|
747
711
|
parse( text, fileName = null ) {
|
|
748
712
|
|
|
749
|
-
const loader = this.loader;
|
|
713
|
+
const loader = this.loader;
|
|
750
714
|
|
|
715
|
+
// final results
|
|
751
716
|
const faces = [];
|
|
752
717
|
const lineSegments = [];
|
|
753
718
|
const conditionalSegments = [];
|
|
754
719
|
const subobjects = [];
|
|
755
720
|
const materials = {};
|
|
756
|
-
|
|
757
721
|
const getLocalMaterial = colorCode => {
|
|
758
722
|
|
|
759
723
|
return materials[ colorCode ] || null;
|
|
@@ -764,8 +728,9 @@
|
|
|
764
728
|
let category = null;
|
|
765
729
|
let keywords = null;
|
|
766
730
|
let author = null;
|
|
767
|
-
let totalFaces = 0;
|
|
731
|
+
let totalFaces = 0;
|
|
768
732
|
|
|
733
|
+
// split into lines
|
|
769
734
|
if ( text.indexOf( '\r\n' ) !== - 1 ) {
|
|
770
735
|
|
|
771
736
|
// This is faster than String.split with regex that splits on both
|
|
@@ -782,20 +747,21 @@
|
|
|
782
747
|
let bfcCCW = true;
|
|
783
748
|
let bfcInverted = false;
|
|
784
749
|
let bfcCull = true;
|
|
785
|
-
let
|
|
750
|
+
let startingBuildingStep = false;
|
|
786
751
|
|
|
752
|
+
// Parse all line commands
|
|
787
753
|
for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) {
|
|
788
754
|
|
|
789
755
|
const line = lines[ lineIndex ];
|
|
790
756
|
if ( line.length === 0 ) continue;
|
|
791
|
-
|
|
792
757
|
if ( parsingEmbeddedFiles ) {
|
|
793
758
|
|
|
794
759
|
if ( line.startsWith( '0 FILE ' ) ) {
|
|
795
760
|
|
|
796
761
|
// Save previous embedded file in the cache
|
|
797
|
-
this.setData( currentEmbeddedFileName, currentEmbeddedText );
|
|
762
|
+
this.setData( currentEmbeddedFileName, currentEmbeddedText );
|
|
798
763
|
|
|
764
|
+
// New embedded text file
|
|
799
765
|
currentEmbeddedFileName = line.substring( 7 );
|
|
800
766
|
currentEmbeddedText = '';
|
|
801
767
|
|
|
@@ -811,15 +777,14 @@
|
|
|
811
777
|
|
|
812
778
|
const lp = new LineParser( line, lineIndex + 1 );
|
|
813
779
|
lp.seekNonSpace();
|
|
814
|
-
|
|
815
780
|
if ( lp.isAtTheEnd() ) {
|
|
816
781
|
|
|
817
782
|
// Empty line
|
|
818
783
|
continue;
|
|
819
784
|
|
|
820
|
-
}
|
|
821
|
-
|
|
785
|
+
}
|
|
822
786
|
|
|
787
|
+
// Parse the line type
|
|
823
788
|
const lineType = lp.getToken();
|
|
824
789
|
let material;
|
|
825
790
|
let colorCode;
|
|
@@ -827,14 +792,12 @@
|
|
|
827
792
|
let ccw;
|
|
828
793
|
let doubleSided;
|
|
829
794
|
let v0, v1, v2, v3, c0, c1;
|
|
830
|
-
|
|
831
795
|
switch ( lineType ) {
|
|
832
796
|
|
|
833
797
|
// Line type 0: Comment or META
|
|
834
798
|
case '0':
|
|
835
799
|
// Parse meta directive
|
|
836
800
|
const meta = lp.getToken();
|
|
837
|
-
|
|
838
801
|
if ( meta ) {
|
|
839
802
|
|
|
840
803
|
switch ( meta ) {
|
|
@@ -842,10 +805,8 @@
|
|
|
842
805
|
case '!LDRAW_ORG':
|
|
843
806
|
type = lp.getToken();
|
|
844
807
|
break;
|
|
845
|
-
|
|
846
808
|
case '!COLOUR':
|
|
847
809
|
material = loader.parseColorMetaDirective( lp );
|
|
848
|
-
|
|
849
810
|
if ( material ) {
|
|
850
811
|
|
|
851
812
|
materials[ material.userData.code ] = material;
|
|
@@ -857,14 +818,11 @@
|
|
|
857
818
|
}
|
|
858
819
|
|
|
859
820
|
break;
|
|
860
|
-
|
|
861
821
|
case '!CATEGORY':
|
|
862
822
|
category = lp.getToken();
|
|
863
823
|
break;
|
|
864
|
-
|
|
865
824
|
case '!KEYWORDS':
|
|
866
825
|
const newKeywords = lp.getRemainingString().split( ',' );
|
|
867
|
-
|
|
868
826
|
if ( newKeywords.length > 0 ) {
|
|
869
827
|
|
|
870
828
|
if ( ! keywords ) {
|
|
@@ -882,7 +840,6 @@
|
|
|
882
840
|
}
|
|
883
841
|
|
|
884
842
|
break;
|
|
885
|
-
|
|
886
843
|
case 'FILE':
|
|
887
844
|
if ( lineIndex > 0 ) {
|
|
888
845
|
|
|
@@ -896,13 +853,11 @@
|
|
|
896
853
|
}
|
|
897
854
|
|
|
898
855
|
break;
|
|
899
|
-
|
|
900
856
|
case 'BFC':
|
|
901
857
|
// Changes to the backface culling state
|
|
902
858
|
while ( ! lp.isAtTheEnd() ) {
|
|
903
859
|
|
|
904
860
|
const token = lp.getToken();
|
|
905
|
-
|
|
906
861
|
switch ( token ) {
|
|
907
862
|
|
|
908
863
|
case 'CERTIFY':
|
|
@@ -910,21 +865,17 @@
|
|
|
910
865
|
bfcCertified = token === 'CERTIFY';
|
|
911
866
|
bfcCCW = true;
|
|
912
867
|
break;
|
|
913
|
-
|
|
914
868
|
case 'CW':
|
|
915
869
|
case 'CCW':
|
|
916
870
|
bfcCCW = token === 'CCW';
|
|
917
871
|
break;
|
|
918
|
-
|
|
919
872
|
case 'INVERTNEXT':
|
|
920
873
|
bfcInverted = true;
|
|
921
874
|
break;
|
|
922
|
-
|
|
923
875
|
case 'CLIP':
|
|
924
876
|
case 'NOCLIP':
|
|
925
877
|
bfcCull = token === 'CLIP';
|
|
926
878
|
break;
|
|
927
|
-
|
|
928
879
|
default:
|
|
929
880
|
console.warn( 'THREE.LDrawLoader: BFC directive "' + token + '" is unknown.' );
|
|
930
881
|
break;
|
|
@@ -934,15 +885,12 @@
|
|
|
934
885
|
}
|
|
935
886
|
|
|
936
887
|
break;
|
|
937
|
-
|
|
938
888
|
case 'STEP':
|
|
939
|
-
|
|
889
|
+
startingBuildingStep = true;
|
|
940
890
|
break;
|
|
941
|
-
|
|
942
891
|
case 'Author:':
|
|
943
892
|
author = lp.getToken();
|
|
944
893
|
break;
|
|
945
|
-
|
|
946
894
|
default:
|
|
947
895
|
// Other meta directives are not implemented
|
|
948
896
|
break;
|
|
@@ -952,8 +900,8 @@
|
|
|
952
900
|
}
|
|
953
901
|
|
|
954
902
|
break;
|
|
955
|
-
// Line type 1: Sub-object file
|
|
956
903
|
|
|
904
|
+
// Line type 1: Sub-object file
|
|
957
905
|
case '1':
|
|
958
906
|
colorCode = lp.getToken();
|
|
959
907
|
material = getLocalMaterial( colorCode );
|
|
@@ -971,7 +919,6 @@
|
|
|
971
919
|
const m8 = parseFloat( lp.getToken() );
|
|
972
920
|
const matrix = new THREE.Matrix4().set( m0, m1, m2, posX, m3, m4, m5, posY, m6, m7, m8, posZ, 0, 0, 0, 1 );
|
|
973
921
|
let fileName = lp.getRemainingString().trim().replace( /\\/g, '/' );
|
|
974
|
-
|
|
975
922
|
if ( loader.fileMap[ fileName ] ) {
|
|
976
923
|
|
|
977
924
|
// Found the subobject path in the preloaded file path map
|
|
@@ -998,12 +945,13 @@
|
|
|
998
945
|
matrix: matrix,
|
|
999
946
|
fileName: fileName,
|
|
1000
947
|
inverted: bfcInverted,
|
|
1001
|
-
|
|
948
|
+
startingBuildingStep: startingBuildingStep
|
|
1002
949
|
} );
|
|
950
|
+
startingBuildingStep = false;
|
|
1003
951
|
bfcInverted = false;
|
|
1004
952
|
break;
|
|
1005
|
-
// Line type 2: Line segment
|
|
1006
953
|
|
|
954
|
+
// Line type 2: Line segment
|
|
1007
955
|
case '2':
|
|
1008
956
|
colorCode = lp.getToken();
|
|
1009
957
|
material = getLocalMaterial( colorCode );
|
|
@@ -1016,8 +964,8 @@
|
|
|
1016
964
|
};
|
|
1017
965
|
lineSegments.push( segment );
|
|
1018
966
|
break;
|
|
1019
|
-
// Line type 5: Conditional Line segment
|
|
1020
967
|
|
|
968
|
+
// Line type 5: Conditional Line segment
|
|
1021
969
|
case '5':
|
|
1022
970
|
colorCode = lp.getToken();
|
|
1023
971
|
material = getLocalMaterial( colorCode );
|
|
@@ -1033,14 +981,13 @@
|
|
|
1033
981
|
};
|
|
1034
982
|
conditionalSegments.push( segment );
|
|
1035
983
|
break;
|
|
1036
|
-
// Line type 3: Triangle
|
|
1037
984
|
|
|
985
|
+
// Line type 3: Triangle
|
|
1038
986
|
case '3':
|
|
1039
987
|
colorCode = lp.getToken();
|
|
1040
988
|
material = getLocalMaterial( colorCode );
|
|
1041
989
|
ccw = bfcCCW;
|
|
1042
990
|
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1043
|
-
|
|
1044
991
|
if ( ccw === true ) {
|
|
1045
992
|
|
|
1046
993
|
v0 = lp.getVector();
|
|
@@ -1063,7 +1010,6 @@
|
|
|
1063
1010
|
normals: [ null, null, null ]
|
|
1064
1011
|
} );
|
|
1065
1012
|
totalFaces ++;
|
|
1066
|
-
|
|
1067
1013
|
if ( doubleSided === true ) {
|
|
1068
1014
|
|
|
1069
1015
|
faces.push( {
|
|
@@ -1078,14 +1024,13 @@
|
|
|
1078
1024
|
}
|
|
1079
1025
|
|
|
1080
1026
|
break;
|
|
1081
|
-
// Line type 4: Quadrilateral
|
|
1082
1027
|
|
|
1028
|
+
// Line type 4: Quadrilateral
|
|
1083
1029
|
case '4':
|
|
1084
1030
|
colorCode = lp.getToken();
|
|
1085
1031
|
material = getLocalMaterial( colorCode );
|
|
1086
1032
|
ccw = bfcCCW;
|
|
1087
1033
|
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1088
|
-
|
|
1089
1034
|
if ( ccw === true ) {
|
|
1090
1035
|
|
|
1091
1036
|
v0 = lp.getVector();
|
|
@@ -1100,10 +1045,10 @@
|
|
|
1100
1045
|
v1 = lp.getVector();
|
|
1101
1046
|
v0 = lp.getVector();
|
|
1102
1047
|
|
|
1103
|
-
}
|
|
1104
|
-
// account for the doubling of vertices later when smoothing normals.
|
|
1105
|
-
|
|
1048
|
+
}
|
|
1106
1049
|
|
|
1050
|
+
// specifically place the triangle diagonal in the v0 and v1 slots so we can
|
|
1051
|
+
// account for the doubling of vertices later when smoothing normals.
|
|
1107
1052
|
faces.push( {
|
|
1108
1053
|
material: material,
|
|
1109
1054
|
colorCode: colorCode,
|
|
@@ -1112,7 +1057,6 @@
|
|
|
1112
1057
|
normals: [ null, null, null, null ]
|
|
1113
1058
|
} );
|
|
1114
1059
|
totalFaces += 2;
|
|
1115
|
-
|
|
1116
1060
|
if ( doubleSided === true ) {
|
|
1117
1061
|
|
|
1118
1062
|
faces.push( {
|
|
@@ -1127,7 +1071,6 @@
|
|
|
1127
1071
|
}
|
|
1128
1072
|
|
|
1129
1073
|
break;
|
|
1130
|
-
|
|
1131
1074
|
default:
|
|
1132
1075
|
throw new Error( 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.' );
|
|
1133
1076
|
|
|
@@ -1151,20 +1094,19 @@
|
|
|
1151
1094
|
author,
|
|
1152
1095
|
subobjects,
|
|
1153
1096
|
totalFaces,
|
|
1154
|
-
|
|
1097
|
+
startingBuildingStep,
|
|
1155
1098
|
materials,
|
|
1156
1099
|
fileName,
|
|
1157
1100
|
group: null
|
|
1158
1101
|
};
|
|
1159
1102
|
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1103
|
+
}
|
|
1162
1104
|
|
|
1105
|
+
// returns an (optionally cloned) instance of the data
|
|
1163
1106
|
getData( fileName, clone = true ) {
|
|
1164
1107
|
|
|
1165
1108
|
const key = fileName.toLowerCase();
|
|
1166
1109
|
const result = this._cache[ key ];
|
|
1167
|
-
|
|
1168
1110
|
if ( result === null || result instanceof Promise ) {
|
|
1169
1111
|
|
|
1170
1112
|
return null;
|
|
@@ -1181,14 +1123,13 @@
|
|
|
1181
1123
|
|
|
1182
1124
|
}
|
|
1183
1125
|
|
|
1184
|
-
}
|
|
1185
|
-
// the data is ready to use and can be retrieved synchronously with "getData".
|
|
1186
|
-
|
|
1126
|
+
}
|
|
1187
1127
|
|
|
1128
|
+
// kicks off a fetch and parse of the requested data if it hasn't already been loaded. Returns when
|
|
1129
|
+
// the data is ready to use and can be retrieved synchronously with "getData".
|
|
1188
1130
|
async ensureDataLoaded( fileName ) {
|
|
1189
1131
|
|
|
1190
1132
|
const key = fileName.toLowerCase();
|
|
1191
|
-
|
|
1192
1133
|
if ( ! ( key in this._cache ) ) {
|
|
1193
1134
|
|
|
1194
1135
|
// replace the promise with a copy of the parsed data for immediate processing
|
|
@@ -1204,9 +1145,9 @@
|
|
|
1204
1145
|
|
|
1205
1146
|
await this._cache[ key ];
|
|
1206
1147
|
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1148
|
+
}
|
|
1209
1149
|
|
|
1150
|
+
// sets the data in the cache from parsed data
|
|
1210
1151
|
setData( fileName, text ) {
|
|
1211
1152
|
|
|
1212
1153
|
const key = fileName.toLowerCase();
|
|
@@ -1214,14 +1155,13 @@
|
|
|
1214
1155
|
|
|
1215
1156
|
}
|
|
1216
1157
|
|
|
1217
|
-
}
|
|
1218
|
-
// an edge then the passthroughColorCode is used.
|
|
1219
|
-
|
|
1158
|
+
}
|
|
1220
1159
|
|
|
1160
|
+
// returns the material for an associated color code. If the color code is 16 for a face or 24 for
|
|
1161
|
+
// an edge then the passthroughColorCode is used.
|
|
1221
1162
|
function getMaterialFromCode( colorCode, parentColorCode, materialHierarchy, forEdge ) {
|
|
1222
1163
|
|
|
1223
1164
|
const isPassthrough = ! forEdge && colorCode === MAIN_COLOUR_CODE || forEdge && colorCode === MAIN_EDGE_COLOUR_CODE;
|
|
1224
|
-
|
|
1225
1165
|
if ( isPassthrough ) {
|
|
1226
1166
|
|
|
1227
1167
|
colorCode = parentColorCode;
|
|
@@ -1230,9 +1170,9 @@
|
|
|
1230
1170
|
|
|
1231
1171
|
return materialHierarchy[ colorCode ] || null;
|
|
1232
1172
|
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1173
|
+
}
|
|
1235
1174
|
|
|
1175
|
+
// Class used to parse and build LDraw parts as three.js objects and cache them if they're a "Part" type.
|
|
1236
1176
|
class LDrawPartsGeometryCache {
|
|
1237
1177
|
|
|
1238
1178
|
constructor( loader ) {
|
|
@@ -1241,29 +1181,30 @@
|
|
|
1241
1181
|
this.parseCache = new LDrawParsedCache( loader );
|
|
1242
1182
|
this._cache = {};
|
|
1243
1183
|
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1184
|
+
}
|
|
1246
1185
|
|
|
1186
|
+
// Convert the given file information into a mesh by processing subobjects.
|
|
1247
1187
|
async processIntoMesh( info ) {
|
|
1248
1188
|
|
|
1249
1189
|
const loader = this.loader;
|
|
1250
1190
|
const parseCache = this.parseCache;
|
|
1251
|
-
const faceMaterials = new Set();
|
|
1252
|
-
// piece object.
|
|
1191
|
+
const faceMaterials = new Set();
|
|
1253
1192
|
|
|
1193
|
+
// Processes the part subobject information to load child parts and merge geometry onto part
|
|
1194
|
+
// piece object.
|
|
1254
1195
|
const processInfoSubobjects = async ( info, subobject = null ) => {
|
|
1255
1196
|
|
|
1256
1197
|
const subobjects = info.subobjects;
|
|
1257
|
-
const promises = [];
|
|
1258
|
-
// group which lets instruction steps apply correctly.
|
|
1198
|
+
const promises = [];
|
|
1259
1199
|
|
|
1200
|
+
// Trigger load of all subobjects. If a subobject isn't a primitive then load it as a separate
|
|
1201
|
+
// group which lets instruction steps apply correctly.
|
|
1260
1202
|
for ( let i = 0, l = subobjects.length; i < l; i ++ ) {
|
|
1261
1203
|
|
|
1262
1204
|
const subobject = subobjects[ i ];
|
|
1263
1205
|
const promise = parseCache.ensureDataLoaded( subobject.fileName ).then( () => {
|
|
1264
1206
|
|
|
1265
1207
|
const subobjectInfo = parseCache.getData( subobject.fileName, false );
|
|
1266
|
-
|
|
1267
1208
|
if ( ! isPrimitiveType( subobjectInfo.type ) ) {
|
|
1268
1209
|
|
|
1269
1210
|
return this.loadModel( subobject.fileName ).catch( error => {
|
|
@@ -1290,42 +1231,40 @@
|
|
|
1290
1231
|
group.userData.fileName = info.fileName;
|
|
1291
1232
|
info.group = group;
|
|
1292
1233
|
const subobjectInfos = await Promise.all( promises );
|
|
1293
|
-
|
|
1294
1234
|
for ( let i = 0, l = subobjectInfos.length; i < l; i ++ ) {
|
|
1295
1235
|
|
|
1296
1236
|
const subobject = info.subobjects[ i ];
|
|
1297
1237
|
const subobjectInfo = subobjectInfos[ i ];
|
|
1298
|
-
|
|
1299
1238
|
if ( subobjectInfo === null ) {
|
|
1300
1239
|
|
|
1301
1240
|
// the subobject failed to load
|
|
1302
1241
|
continue;
|
|
1303
1242
|
|
|
1304
|
-
}
|
|
1305
|
-
|
|
1243
|
+
}
|
|
1306
1244
|
|
|
1245
|
+
// if the subobject was loaded as a separate group then apply the parent scopes materials
|
|
1307
1246
|
if ( subobjectInfo.isGroup ) {
|
|
1308
1247
|
|
|
1309
1248
|
const subobjectGroup = subobjectInfo;
|
|
1310
1249
|
subobject.matrix.decompose( subobjectGroup.position, subobjectGroup.quaternion, subobjectGroup.scale );
|
|
1311
|
-
subobjectGroup.userData.
|
|
1250
|
+
subobjectGroup.userData.startingBuildingStep = subobject.startingBuildingStep;
|
|
1312
1251
|
subobjectGroup.name = subobject.fileName;
|
|
1313
1252
|
loader.applyMaterialsToMesh( subobjectGroup, subobject.colorCode, info.materials );
|
|
1314
1253
|
subobjectGroup.userData.colorCode = subobject.colorCode;
|
|
1315
1254
|
group.add( subobjectGroup );
|
|
1316
1255
|
continue;
|
|
1317
1256
|
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1257
|
+
}
|
|
1320
1258
|
|
|
1259
|
+
// add the subobject group if it has children in case it has both children and primitives
|
|
1321
1260
|
if ( subobjectInfo.group.children.length ) {
|
|
1322
1261
|
|
|
1323
1262
|
group.add( subobjectInfo.group );
|
|
1324
1263
|
|
|
1325
|
-
}
|
|
1326
|
-
// to the parent primitives list.
|
|
1327
|
-
|
|
1264
|
+
}
|
|
1328
1265
|
|
|
1266
|
+
// transform the primitives into the local space of the parent piece and append them to
|
|
1267
|
+
// to the parent primitives list.
|
|
1329
1268
|
const parentLineSegments = info.lineSegments;
|
|
1330
1269
|
const parentConditionalSegments = info.conditionalSegments;
|
|
1331
1270
|
const parentFaces = info.faces;
|
|
@@ -1337,7 +1276,6 @@
|
|
|
1337
1276
|
const matrixScaleInverted = matrix.determinant() < 0;
|
|
1338
1277
|
const colorCode = subobject.colorCode;
|
|
1339
1278
|
const lineColorCode = colorCode === MAIN_COLOUR_CODE ? MAIN_EDGE_COLOUR_CODE : colorCode;
|
|
1340
|
-
|
|
1341
1279
|
for ( let i = 0, l = lineSegments.length; i < l; i ++ ) {
|
|
1342
1280
|
|
|
1343
1281
|
const ls = lineSegments[ i ];
|
|
@@ -1369,7 +1307,6 @@
|
|
|
1369
1307
|
|
|
1370
1308
|
const tri = faces[ i ];
|
|
1371
1309
|
const vertices = tri.vertices;
|
|
1372
|
-
|
|
1373
1310
|
for ( let i = 0, l = vertices.length; i < l; i ++ ) {
|
|
1374
1311
|
|
|
1375
1312
|
vertices[ i ].applyMatrix4( matrix );
|
|
@@ -1378,9 +1315,10 @@
|
|
|
1378
1315
|
|
|
1379
1316
|
tri.colorCode = tri.colorCode === MAIN_COLOUR_CODE ? colorCode : tri.colorCode;
|
|
1380
1317
|
tri.material = tri.material || getMaterialFromCode( tri.colorCode, colorCode, info.materials, false );
|
|
1381
|
-
faceMaterials.add( tri.colorCode );
|
|
1382
|
-
// needs to be flipped.
|
|
1318
|
+
faceMaterials.add( tri.colorCode );
|
|
1383
1319
|
|
|
1320
|
+
// If the scale of the object is negated then the triangle winding order
|
|
1321
|
+
// needs to be flipped.
|
|
1384
1322
|
if ( matrixScaleInverted !== inverted ) {
|
|
1385
1323
|
|
|
1386
1324
|
vertices.reverse();
|
|
@@ -1393,10 +1331,10 @@
|
|
|
1393
1331
|
|
|
1394
1332
|
info.totalFaces += subobjectInfo.totalFaces;
|
|
1395
1333
|
|
|
1396
|
-
}
|
|
1397
|
-
// to material scoping.
|
|
1398
|
-
|
|
1334
|
+
}
|
|
1399
1335
|
|
|
1336
|
+
// Apply the parent subobjects pass through material code to this object. This is done several times due
|
|
1337
|
+
// to material scoping.
|
|
1400
1338
|
if ( subobject ) {
|
|
1401
1339
|
|
|
1402
1340
|
loader.applyMaterialsToMesh( group, subobject.colorCode, info.materials );
|
|
@@ -1406,9 +1344,9 @@
|
|
|
1406
1344
|
|
|
1407
1345
|
return info;
|
|
1408
1346
|
|
|
1409
|
-
};
|
|
1410
|
-
|
|
1347
|
+
};
|
|
1411
1348
|
|
|
1349
|
+
// Track material use to see if we need to use the normal smooth slow path for hard edges.
|
|
1412
1350
|
for ( let i = 0, l = info.faces; i < l; i ++ ) {
|
|
1413
1351
|
|
|
1414
1352
|
faceMaterials.add( info.faces[ i ].colorCode );
|
|
@@ -1416,18 +1354,16 @@
|
|
|
1416
1354
|
}
|
|
1417
1355
|
|
|
1418
1356
|
await processInfoSubobjects( info );
|
|
1419
|
-
|
|
1420
1357
|
if ( loader.smoothNormals ) {
|
|
1421
1358
|
|
|
1422
1359
|
const checkSubSegments = faceMaterials.size > 1;
|
|
1423
1360
|
generateFaceNormals( info.faces );
|
|
1424
1361
|
smoothNormals( info.faces, info.lineSegments, checkSubSegments );
|
|
1425
1362
|
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1363
|
+
}
|
|
1428
1364
|
|
|
1365
|
+
// Add the primitive objects and metadata.
|
|
1429
1366
|
const group = info.group;
|
|
1430
|
-
|
|
1431
1367
|
if ( info.faces.length > 0 ) {
|
|
1432
1368
|
|
|
1433
1369
|
group.add( createObject( info.faces, 3, false, info.totalFaces ) );
|
|
@@ -1449,13 +1385,11 @@
|
|
|
1449
1385
|
return group;
|
|
1450
1386
|
|
|
1451
1387
|
}
|
|
1452
|
-
|
|
1453
1388
|
hasCachedModel( fileName ) {
|
|
1454
1389
|
|
|
1455
1390
|
return fileName !== null && fileName.toLowerCase() in this._cache;
|
|
1456
1391
|
|
|
1457
1392
|
}
|
|
1458
|
-
|
|
1459
1393
|
async getCachedModel( fileName ) {
|
|
1460
1394
|
|
|
1461
1395
|
if ( fileName !== null && this.hasCachedModel( fileName ) ) {
|
|
@@ -1470,14 +1404,13 @@
|
|
|
1470
1404
|
|
|
1471
1405
|
}
|
|
1472
1406
|
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1407
|
+
}
|
|
1475
1408
|
|
|
1409
|
+
// Loads and parses the model with the given file name. Returns a cached copy if available.
|
|
1476
1410
|
async loadModel( fileName ) {
|
|
1477
1411
|
|
|
1478
1412
|
const parseCache = this.parseCache;
|
|
1479
1413
|
const key = fileName.toLowerCase();
|
|
1480
|
-
|
|
1481
1414
|
if ( this.hasCachedModel( fileName ) ) {
|
|
1482
1415
|
|
|
1483
1416
|
// Return cached model if available.
|
|
@@ -1489,37 +1422,37 @@
|
|
|
1489
1422
|
// Ensure the file data is loaded and pre parsed.
|
|
1490
1423
|
await parseCache.ensureDataLoaded( fileName );
|
|
1491
1424
|
const info = parseCache.getData( fileName );
|
|
1492
|
-
const promise = this.processIntoMesh( info );
|
|
1425
|
+
const promise = this.processIntoMesh( info );
|
|
1426
|
+
|
|
1427
|
+
// Now that the file has loaded it's possible that another part parse has been waiting in parallel
|
|
1493
1428
|
// so check the cache again to see if it's been added since the last async operation so we don't
|
|
1494
1429
|
// do unnecessary work.
|
|
1495
|
-
|
|
1496
1430
|
if ( this.hasCachedModel( fileName ) ) {
|
|
1497
1431
|
|
|
1498
1432
|
return this.getCachedModel( fileName );
|
|
1499
1433
|
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1434
|
+
}
|
|
1502
1435
|
|
|
1436
|
+
// Cache object if it's a part so it can be reused later.
|
|
1503
1437
|
if ( isPartType( info.type ) ) {
|
|
1504
1438
|
|
|
1505
1439
|
this._cache[ key ] = promise;
|
|
1506
1440
|
|
|
1507
|
-
}
|
|
1508
|
-
|
|
1441
|
+
}
|
|
1509
1442
|
|
|
1443
|
+
// return a copy
|
|
1510
1444
|
const group = await promise;
|
|
1511
1445
|
return group.clone();
|
|
1512
1446
|
|
|
1513
1447
|
}
|
|
1514
1448
|
|
|
1515
|
-
}
|
|
1516
|
-
|
|
1449
|
+
}
|
|
1517
1450
|
|
|
1451
|
+
// parses the given model text into a renderable object. Returns cached copy if available.
|
|
1518
1452
|
async parseModel( text ) {
|
|
1519
1453
|
|
|
1520
1454
|
const parseCache = this.parseCache;
|
|
1521
1455
|
const info = parseCache.parse( text );
|
|
1522
|
-
|
|
1523
1456
|
if ( isPartType( info.type ) && this.hasCachedModel( info.fileName ) ) {
|
|
1524
1457
|
|
|
1525
1458
|
return this.getCachedModel( info.fileName );
|
|
@@ -1531,7 +1464,6 @@
|
|
|
1531
1464
|
}
|
|
1532
1465
|
|
|
1533
1466
|
}
|
|
1534
|
-
|
|
1535
1467
|
function sortByMaterial( a, b ) {
|
|
1536
1468
|
|
|
1537
1469
|
if ( a.colorCode === b.colorCode ) {
|
|
@@ -1554,9 +1486,9 @@
|
|
|
1554
1486
|
|
|
1555
1487
|
// Creates a THREE.LineSegments (elementSize = 2) or a THREE.Mesh (elementSize = 3 )
|
|
1556
1488
|
// With per face / segment material, implemented with mesh groups and materials array
|
|
1489
|
+
|
|
1557
1490
|
// Sort the faces or line segments by color code to make later the mesh groups
|
|
1558
1491
|
elements.sort( sortByMaterial );
|
|
1559
|
-
|
|
1560
1492
|
if ( totalElements === null ) {
|
|
1561
1493
|
|
|
1562
1494
|
totalElements = elements.length;
|
|
@@ -1572,12 +1504,10 @@
|
|
|
1572
1504
|
let index0 = 0;
|
|
1573
1505
|
let numGroupVerts = 0;
|
|
1574
1506
|
let offset = 0;
|
|
1575
|
-
|
|
1576
1507
|
for ( let iElem = 0, nElem = elements.length; iElem < nElem; iElem ++ ) {
|
|
1577
1508
|
|
|
1578
1509
|
const elem = elements[ iElem ];
|
|
1579
1510
|
let vertices = elem.vertices;
|
|
1580
|
-
|
|
1581
1511
|
if ( vertices.length === 4 ) {
|
|
1582
1512
|
|
|
1583
1513
|
quadArray[ 0 ] = vertices[ 0 ];
|
|
@@ -1598,9 +1528,9 @@
|
|
|
1598
1528
|
positions[ index + 1 ] = v.y;
|
|
1599
1529
|
positions[ index + 2 ] = v.z;
|
|
1600
1530
|
|
|
1601
|
-
}
|
|
1602
|
-
|
|
1531
|
+
}
|
|
1603
1532
|
|
|
1533
|
+
// create the normals array if this is a set of faces
|
|
1604
1534
|
if ( elementSize === 3 ) {
|
|
1605
1535
|
|
|
1606
1536
|
if ( ! elem.faceNormal ) {
|
|
@@ -1608,17 +1538,13 @@
|
|
|
1608
1538
|
const v0 = vertices[ 0 ];
|
|
1609
1539
|
const v1 = vertices[ 1 ];
|
|
1610
1540
|
const v2 = vertices[ 2 ];
|
|
1611
|
-
|
|
1612
1541
|
_tempVec0.subVectors( v1, v0 );
|
|
1613
|
-
|
|
1614
1542
|
_tempVec1.subVectors( v2, v1 );
|
|
1615
|
-
|
|
1616
1543
|
elem.faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize();
|
|
1617
1544
|
|
|
1618
1545
|
}
|
|
1619
1546
|
|
|
1620
1547
|
let elemNormals = elem.normals;
|
|
1621
|
-
|
|
1622
1548
|
if ( elemNormals.length === 4 ) {
|
|
1623
1549
|
|
|
1624
1550
|
quadArray[ 0 ] = elemNormals[ 0 ];
|
|
@@ -1635,7 +1561,6 @@
|
|
|
1635
1561
|
|
|
1636
1562
|
// use face normal if a vertex normal is not provided
|
|
1637
1563
|
let n = elem.faceNormal;
|
|
1638
|
-
|
|
1639
1564
|
if ( elemNormals[ j ] ) {
|
|
1640
1565
|
|
|
1641
1566
|
n = elemNormals[ j ].norm;
|
|
@@ -1660,7 +1585,6 @@
|
|
|
1660
1585
|
}
|
|
1661
1586
|
|
|
1662
1587
|
const material = elem.material;
|
|
1663
|
-
|
|
1664
1588
|
if ( material !== null ) {
|
|
1665
1589
|
|
|
1666
1590
|
if ( elementSize === 3 ) {
|
|
@@ -1710,7 +1634,6 @@
|
|
|
1710
1634
|
}
|
|
1711
1635
|
|
|
1712
1636
|
bufferGeometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
|
|
1713
|
-
|
|
1714
1637
|
if ( normals !== null ) {
|
|
1715
1638
|
|
|
1716
1639
|
bufferGeometry.setAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
|
|
@@ -1718,7 +1641,6 @@
|
|
|
1718
1641
|
}
|
|
1719
1642
|
|
|
1720
1643
|
let object3d = null;
|
|
1721
|
-
|
|
1722
1644
|
if ( elementSize === 2 ) {
|
|
1723
1645
|
|
|
1724
1646
|
if ( isConditionalSegments ) {
|
|
@@ -1743,7 +1665,6 @@
|
|
|
1743
1665
|
const controlArray0 = new Float32Array( elements.length * 3 * 2 );
|
|
1744
1666
|
const controlArray1 = new Float32Array( elements.length * 3 * 2 );
|
|
1745
1667
|
const directionArray = new Float32Array( elements.length * 3 * 2 );
|
|
1746
|
-
|
|
1747
1668
|
for ( let i = 0, l = elements.length; i < l; i ++ ) {
|
|
1748
1669
|
|
|
1749
1670
|
const os = elements[ i ];
|
|
@@ -1783,28 +1704,36 @@
|
|
|
1783
1704
|
|
|
1784
1705
|
return object3d;
|
|
1785
1706
|
|
|
1786
|
-
}
|
|
1707
|
+
}
|
|
1787
1708
|
|
|
1709
|
+
//
|
|
1788
1710
|
|
|
1789
1711
|
class LDrawLoader extends THREE.Loader {
|
|
1790
1712
|
|
|
1791
1713
|
constructor( manager ) {
|
|
1792
1714
|
|
|
1793
|
-
super( manager );
|
|
1715
|
+
super( manager );
|
|
1794
1716
|
|
|
1717
|
+
// Array of THREE.Material
|
|
1795
1718
|
this.materials = [];
|
|
1796
|
-
this.materialLibrary = {};
|
|
1719
|
+
this.materialLibrary = {};
|
|
1797
1720
|
|
|
1798
|
-
|
|
1721
|
+
// This also allows to handle the embedded text files ("0 FILE" lines)
|
|
1722
|
+
this.partsCache = new LDrawPartsGeometryCache( this );
|
|
1799
1723
|
|
|
1800
|
-
|
|
1724
|
+
// This object is a map from file names to paths. It agilizes the paths search. If it is not set then files will be searched by trial and error.
|
|
1725
|
+
this.fileMap = {};
|
|
1801
1726
|
|
|
1802
|
-
|
|
1727
|
+
// Initializes the materials library with default materials
|
|
1728
|
+
this.setMaterials( [] );
|
|
1803
1729
|
|
|
1804
|
-
|
|
1730
|
+
// If this flag is set to true the vertex normals will be smoothed.
|
|
1731
|
+
this.smoothNormals = true;
|
|
1805
1732
|
|
|
1806
|
-
|
|
1733
|
+
// The path to load parts from the LDraw parts library from.
|
|
1734
|
+
this.partsLibraryPath = '';
|
|
1807
1735
|
|
|
1736
|
+
// Material assigned to not available colors for meshes and edges
|
|
1808
1737
|
this.missingColorMaterial = new THREE.MeshStandardMaterial( {
|
|
1809
1738
|
color: 0xFF00FF,
|
|
1810
1739
|
roughness: 0.3,
|
|
@@ -1824,14 +1753,12 @@
|
|
|
1824
1753
|
this.missingEdgeColorMaterial.userData.conditionalEdgeMaterial = this.missingConditionalEdgeColorMaterial;
|
|
1825
1754
|
|
|
1826
1755
|
}
|
|
1827
|
-
|
|
1828
1756
|
setPartsLibraryPath( path ) {
|
|
1829
1757
|
|
|
1830
1758
|
this.partsLibraryPath = path;
|
|
1831
1759
|
return this;
|
|
1832
1760
|
|
|
1833
1761
|
}
|
|
1834
|
-
|
|
1835
1762
|
async preloadMaterials( url ) {
|
|
1836
1763
|
|
|
1837
1764
|
const fileLoader = new THREE.FileLoader( this.manager );
|
|
@@ -1842,11 +1769,9 @@
|
|
|
1842
1769
|
const colorLineRegex = /^0 !COLOUR/;
|
|
1843
1770
|
const lines = text.split( /[\n\r]/g );
|
|
1844
1771
|
const materials = [];
|
|
1845
|
-
|
|
1846
1772
|
for ( let i = 0, l = lines.length; i < l; i ++ ) {
|
|
1847
1773
|
|
|
1848
1774
|
const line = lines[ i ];
|
|
1849
|
-
|
|
1850
1775
|
if ( colorLineRegex.test( line ) ) {
|
|
1851
1776
|
|
|
1852
1777
|
const directive = line.replace( colorLineRegex, '' );
|
|
@@ -1860,7 +1785,6 @@
|
|
|
1860
1785
|
this.setMaterials( materials );
|
|
1861
1786
|
|
|
1862
1787
|
}
|
|
1863
|
-
|
|
1864
1788
|
load( url, onLoad, onProgress, onError ) {
|
|
1865
1789
|
|
|
1866
1790
|
const fileLoader = new THREE.FileLoader( this.manager );
|
|
@@ -1872,7 +1796,7 @@
|
|
|
1872
1796
|
this.partsCache.parseModel( text, this.materialLibrary ).then( group => {
|
|
1873
1797
|
|
|
1874
1798
|
this.applyMaterialsToMesh( group, MAIN_COLOUR_CODE, this.materialLibrary, true );
|
|
1875
|
-
this.
|
|
1799
|
+
this.computeBuildingSteps( group );
|
|
1876
1800
|
group.userData.fileName = url;
|
|
1877
1801
|
onLoad( group );
|
|
1878
1802
|
|
|
@@ -1881,50 +1805,45 @@
|
|
|
1881
1805
|
}, onProgress, onError );
|
|
1882
1806
|
|
|
1883
1807
|
}
|
|
1884
|
-
|
|
1885
1808
|
parse( text, onLoad ) {
|
|
1886
1809
|
|
|
1887
1810
|
this.partsCache.parseModel( text, this.materialLibrary ).then( group => {
|
|
1888
1811
|
|
|
1889
1812
|
this.applyMaterialsToMesh( group, MAIN_COLOUR_CODE, this.materialLibrary, true );
|
|
1890
|
-
this.
|
|
1813
|
+
this.computeBuildingSteps( group );
|
|
1891
1814
|
group.userData.fileName = '';
|
|
1892
1815
|
onLoad( group );
|
|
1893
1816
|
|
|
1894
1817
|
} );
|
|
1895
1818
|
|
|
1896
1819
|
}
|
|
1897
|
-
|
|
1898
1820
|
setMaterials( materials ) {
|
|
1899
1821
|
|
|
1900
1822
|
this.materialLibrary = {};
|
|
1901
1823
|
this.materials = [];
|
|
1902
|
-
|
|
1903
1824
|
for ( let i = 0, l = materials.length; i < l; i ++ ) {
|
|
1904
1825
|
|
|
1905
1826
|
this.addMaterial( materials[ i ] );
|
|
1906
1827
|
|
|
1907
|
-
}
|
|
1908
|
-
|
|
1828
|
+
}
|
|
1909
1829
|
|
|
1830
|
+
// Add default main triangle and line edge materials (used in pieces that can be colored with a main color)
|
|
1910
1831
|
this.addMaterial( this.parseColorMetaDirective( new LineParser( 'Main_Colour CODE 16 VALUE #FF8080 EDGE #333333' ) ) );
|
|
1911
1832
|
this.addMaterial( this.parseColorMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) ) );
|
|
1912
1833
|
return this;
|
|
1913
1834
|
|
|
1914
1835
|
}
|
|
1915
|
-
|
|
1916
1836
|
setFileMap( fileMap ) {
|
|
1917
1837
|
|
|
1918
1838
|
this.fileMap = fileMap;
|
|
1919
1839
|
return this;
|
|
1920
1840
|
|
|
1921
1841
|
}
|
|
1922
|
-
|
|
1923
1842
|
addMaterial( material ) {
|
|
1924
1843
|
|
|
1925
1844
|
// Adds a material to the material library which is on top of the parse scopes stack. And also to the materials array
|
|
1926
|
-
const matLib = this.materialLibrary;
|
|
1927
1845
|
|
|
1846
|
+
const matLib = this.materialLibrary;
|
|
1928
1847
|
if ( ! matLib[ material.userData.code ] ) {
|
|
1929
1848
|
|
|
1930
1849
|
this.materials.push( material );
|
|
@@ -1935,7 +1854,6 @@
|
|
|
1935
1854
|
return this;
|
|
1936
1855
|
|
|
1937
1856
|
}
|
|
1938
|
-
|
|
1939
1857
|
getMaterial( colorCode ) {
|
|
1940
1858
|
|
|
1941
1859
|
if ( colorCode.startsWith( '0x2' ) ) {
|
|
@@ -1948,10 +1866,10 @@
|
|
|
1948
1866
|
|
|
1949
1867
|
return this.materialLibrary[ colorCode ] || null;
|
|
1950
1868
|
|
|
1951
|
-
}
|
|
1952
|
-
// in the material array if they need to be filled in.
|
|
1953
|
-
|
|
1869
|
+
}
|
|
1954
1870
|
|
|
1871
|
+
// Applies the appropriate materials to a prebuilt hierarchy of geometry. Assumes that color codes are present
|
|
1872
|
+
// in the material array if they need to be filled in.
|
|
1955
1873
|
applyMaterialsToMesh( group, parentColorCode, materialHierarchy, finalMaterialPass = false ) {
|
|
1956
1874
|
|
|
1957
1875
|
// find any missing materials as indicated by a color code string and replace it with a material from the current material lib
|
|
@@ -1981,10 +1899,11 @@
|
|
|
1981
1899
|
|
|
1982
1900
|
}
|
|
1983
1901
|
|
|
1984
|
-
} );
|
|
1902
|
+
} );
|
|
1903
|
+
|
|
1904
|
+
// Returns the appropriate material for the object (line or face) given color code. If the code is "pass through"
|
|
1985
1905
|
// (24 for lines, 16 for edges) then the pass through color code is used. If that is also pass through then it's
|
|
1986
1906
|
// simply returned for the subsequent material application.
|
|
1987
|
-
|
|
1988
1907
|
function getMaterial( c, colorCode ) {
|
|
1989
1908
|
|
|
1990
1909
|
// if our parent is a passthrough color code and we don't have the current material color available then
|
|
@@ -1997,7 +1916,6 @@
|
|
|
1997
1916
|
|
|
1998
1917
|
const forEdge = c.isLineSegments || c.isConditionalLine;
|
|
1999
1918
|
const isPassthrough = ! forEdge && colorCode === MAIN_COLOUR_CODE || forEdge && colorCode === MAIN_EDGE_COLOUR_CODE;
|
|
2000
|
-
|
|
2001
1919
|
if ( isPassthrough ) {
|
|
2002
1920
|
|
|
2003
1921
|
colorCode = parentColorCode;
|
|
@@ -2005,7 +1923,6 @@
|
|
|
2005
1923
|
}
|
|
2006
1924
|
|
|
2007
1925
|
let material = null;
|
|
2008
|
-
|
|
2009
1926
|
if ( colorCode in materialHierarchy ) {
|
|
2010
1927
|
|
|
2011
1928
|
material = materialHierarchy[ colorCode ];
|
|
@@ -2015,12 +1932,12 @@
|
|
|
2015
1932
|
// see if we can get the final material from from the "getMaterial" function which will attempt to
|
|
2016
1933
|
// parse the "direct" colors
|
|
2017
1934
|
material = loader.getMaterial( colorCode );
|
|
2018
|
-
|
|
2019
1935
|
if ( material === null ) {
|
|
2020
1936
|
|
|
2021
1937
|
// otherwise throw a warning if this is final opportunity to set the material
|
|
2022
|
-
console.warn( `LDrawLoader: Material properties for code ${colorCode} not available.` );
|
|
1938
|
+
console.warn( `LDrawLoader: Material properties for code ${colorCode} not available.` );
|
|
2023
1939
|
|
|
1940
|
+
// And return the 'missing color' material
|
|
2024
1941
|
material = loader.missingColorMaterial;
|
|
2025
1942
|
|
|
2026
1943
|
}
|
|
@@ -2034,7 +1951,6 @@
|
|
|
2034
1951
|
if ( c.isLineSegments ) {
|
|
2035
1952
|
|
|
2036
1953
|
material = material.userData.edgeMaterial;
|
|
2037
|
-
|
|
2038
1954
|
if ( c.isConditionalLine ) {
|
|
2039
1955
|
|
|
2040
1956
|
material = material.userData.conditionalEdgeMaterial;
|
|
@@ -2048,49 +1964,46 @@
|
|
|
2048
1964
|
}
|
|
2049
1965
|
|
|
2050
1966
|
}
|
|
2051
|
-
|
|
2052
1967
|
getMainMaterial() {
|
|
2053
1968
|
|
|
2054
1969
|
return this.getMaterial( MAIN_COLOUR_CODE );
|
|
2055
1970
|
|
|
2056
1971
|
}
|
|
2057
|
-
|
|
2058
1972
|
getMainEdgeMaterial() {
|
|
2059
1973
|
|
|
2060
1974
|
const mat = this.getMaterial( MAIN_EDGE_COLOUR_CODE );
|
|
2061
1975
|
return mat ? mat.userData.edgeMaterial : null;
|
|
2062
1976
|
|
|
2063
1977
|
}
|
|
2064
|
-
|
|
2065
1978
|
parseColorMetaDirective( lineParser ) {
|
|
2066
1979
|
|
|
2067
1980
|
// Parses a color definition and returns a THREE.Material
|
|
2068
|
-
let code = null; // Triangle and line colors
|
|
2069
1981
|
|
|
1982
|
+
let code = null;
|
|
1983
|
+
|
|
1984
|
+
// Triangle and line colors
|
|
2070
1985
|
let color = 0xFF00FF;
|
|
2071
|
-
let edgeColor = 0xFF00FF;
|
|
1986
|
+
let edgeColor = 0xFF00FF;
|
|
2072
1987
|
|
|
1988
|
+
// Transparency
|
|
2073
1989
|
let alpha = 1;
|
|
2074
|
-
let isTransparent = false;
|
|
2075
|
-
|
|
1990
|
+
let isTransparent = false;
|
|
1991
|
+
// Self-illumination:
|
|
2076
1992
|
let luminance = 0;
|
|
2077
1993
|
let finishType = FINISH_TYPE_DEFAULT;
|
|
2078
1994
|
let edgeMaterial = null;
|
|
2079
1995
|
const name = lineParser.getToken();
|
|
2080
|
-
|
|
2081
1996
|
if ( ! name ) {
|
|
2082
1997
|
|
|
2083
1998
|
throw new Error( 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.' );
|
|
2084
1999
|
|
|
2085
|
-
}
|
|
2086
|
-
|
|
2000
|
+
}
|
|
2087
2001
|
|
|
2002
|
+
// Parse tag tokens and their parameters
|
|
2088
2003
|
let token = null;
|
|
2089
|
-
|
|
2090
2004
|
while ( true ) {
|
|
2091
2005
|
|
|
2092
2006
|
token = lineParser.getToken();
|
|
2093
|
-
|
|
2094
2007
|
if ( ! token ) {
|
|
2095
2008
|
|
|
2096
2009
|
break;
|
|
@@ -2104,10 +2017,8 @@
|
|
|
2104
2017
|
case 'CODE':
|
|
2105
2018
|
code = lineParser.getToken();
|
|
2106
2019
|
break;
|
|
2107
|
-
|
|
2108
2020
|
case 'VALUE':
|
|
2109
2021
|
color = lineParser.getToken();
|
|
2110
|
-
|
|
2111
2022
|
if ( color.startsWith( '0x' ) ) {
|
|
2112
2023
|
|
|
2113
2024
|
color = '#' + color.substring( 2 );
|
|
@@ -2119,10 +2030,8 @@
|
|
|
2119
2030
|
}
|
|
2120
2031
|
|
|
2121
2032
|
break;
|
|
2122
|
-
|
|
2123
2033
|
case 'EDGE':
|
|
2124
2034
|
edgeColor = lineParser.getToken();
|
|
2125
|
-
|
|
2126
2035
|
if ( edgeColor.startsWith( '0x' ) ) {
|
|
2127
2036
|
|
|
2128
2037
|
edgeColor = '#' + edgeColor.substring( 2 );
|
|
@@ -2131,23 +2040,20 @@
|
|
|
2131
2040
|
|
|
2132
2041
|
// Try to see if edge color is a color code
|
|
2133
2042
|
edgeMaterial = this.getMaterial( edgeColor );
|
|
2134
|
-
|
|
2135
2043
|
if ( ! edgeMaterial ) {
|
|
2136
2044
|
|
|
2137
2045
|
throw new Error( 'LDrawLoader: Invalid edge color while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
2138
2046
|
|
|
2139
|
-
}
|
|
2140
|
-
|
|
2047
|
+
}
|
|
2141
2048
|
|
|
2049
|
+
// Get the edge material for this triangle material
|
|
2142
2050
|
edgeMaterial = edgeMaterial.userData.edgeMaterial;
|
|
2143
2051
|
|
|
2144
2052
|
}
|
|
2145
2053
|
|
|
2146
2054
|
break;
|
|
2147
|
-
|
|
2148
2055
|
case 'ALPHA':
|
|
2149
2056
|
alpha = parseInt( lineParser.getToken() );
|
|
2150
|
-
|
|
2151
2057
|
if ( isNaN( alpha ) ) {
|
|
2152
2058
|
|
|
2153
2059
|
throw new Error( 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.' );
|
|
@@ -2155,7 +2061,6 @@
|
|
|
2155
2061
|
}
|
|
2156
2062
|
|
|
2157
2063
|
alpha = Math.max( 0, Math.min( 1, alpha / 255 ) );
|
|
2158
|
-
|
|
2159
2064
|
if ( alpha < 1 ) {
|
|
2160
2065
|
|
|
2161
2066
|
isTransparent = true;
|
|
@@ -2163,7 +2068,6 @@
|
|
|
2163
2068
|
}
|
|
2164
2069
|
|
|
2165
2070
|
break;
|
|
2166
|
-
|
|
2167
2071
|
case 'LUMINANCE':
|
|
2168
2072
|
if ( ! parseLuminance( lineParser.getToken() ) ) {
|
|
2169
2073
|
|
|
@@ -2172,32 +2076,25 @@
|
|
|
2172
2076
|
}
|
|
2173
2077
|
|
|
2174
2078
|
break;
|
|
2175
|
-
|
|
2176
2079
|
case 'CHROME':
|
|
2177
2080
|
finishType = FINISH_TYPE_CHROME;
|
|
2178
2081
|
break;
|
|
2179
|
-
|
|
2180
2082
|
case 'PEARLESCENT':
|
|
2181
2083
|
finishType = FINISH_TYPE_PEARLESCENT;
|
|
2182
2084
|
break;
|
|
2183
|
-
|
|
2184
2085
|
case 'RUBBER':
|
|
2185
2086
|
finishType = FINISH_TYPE_RUBBER;
|
|
2186
2087
|
break;
|
|
2187
|
-
|
|
2188
2088
|
case 'MATTE_METALLIC':
|
|
2189
2089
|
finishType = FINISH_TYPE_MATTE_METALLIC;
|
|
2190
2090
|
break;
|
|
2191
|
-
|
|
2192
2091
|
case 'METAL':
|
|
2193
2092
|
finishType = FINISH_TYPE_METAL;
|
|
2194
2093
|
break;
|
|
2195
|
-
|
|
2196
2094
|
case 'MATERIAL':
|
|
2197
2095
|
// Not implemented
|
|
2198
2096
|
lineParser.setToEnd();
|
|
2199
2097
|
break;
|
|
2200
|
-
|
|
2201
2098
|
default:
|
|
2202
2099
|
throw new Error( 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
2203
2100
|
|
|
@@ -2208,7 +2105,6 @@
|
|
|
2208
2105
|
}
|
|
2209
2106
|
|
|
2210
2107
|
let material = null;
|
|
2211
|
-
|
|
2212
2108
|
switch ( finishType ) {
|
|
2213
2109
|
|
|
2214
2110
|
case FINISH_TYPE_DEFAULT:
|
|
@@ -2218,7 +2114,6 @@
|
|
|
2218
2114
|
metalness: 0
|
|
2219
2115
|
} );
|
|
2220
2116
|
break;
|
|
2221
|
-
|
|
2222
2117
|
case FINISH_TYPE_PEARLESCENT:
|
|
2223
2118
|
// Try to imitate pearlescency by making the surface glossy
|
|
2224
2119
|
material = new THREE.MeshStandardMaterial( {
|
|
@@ -2227,7 +2122,6 @@
|
|
|
2227
2122
|
metalness: 0.25
|
|
2228
2123
|
} );
|
|
2229
2124
|
break;
|
|
2230
|
-
|
|
2231
2125
|
case FINISH_TYPE_CHROME:
|
|
2232
2126
|
// Mirror finish surface
|
|
2233
2127
|
material = new THREE.MeshStandardMaterial( {
|
|
@@ -2236,7 +2130,6 @@
|
|
|
2236
2130
|
metalness: 1
|
|
2237
2131
|
} );
|
|
2238
2132
|
break;
|
|
2239
|
-
|
|
2240
2133
|
case FINISH_TYPE_RUBBER:
|
|
2241
2134
|
// Rubber finish
|
|
2242
2135
|
material = new THREE.MeshStandardMaterial( {
|
|
@@ -2245,7 +2138,6 @@
|
|
|
2245
2138
|
metalness: 0
|
|
2246
2139
|
} );
|
|
2247
2140
|
break;
|
|
2248
|
-
|
|
2249
2141
|
case FINISH_TYPE_MATTE_METALLIC:
|
|
2250
2142
|
// Brushed metal finish
|
|
2251
2143
|
material = new THREE.MeshStandardMaterial( {
|
|
@@ -2254,7 +2146,6 @@
|
|
|
2254
2146
|
metalness: 0.4
|
|
2255
2147
|
} );
|
|
2256
2148
|
break;
|
|
2257
|
-
|
|
2258
2149
|
case FINISH_TYPE_METAL:
|
|
2259
2150
|
// Average metal finish
|
|
2260
2151
|
material = new THREE.MeshStandardMaterial( {
|
|
@@ -2263,7 +2154,6 @@
|
|
|
2263
2154
|
metalness: 0.85
|
|
2264
2155
|
} );
|
|
2265
2156
|
break;
|
|
2266
|
-
|
|
2267
2157
|
default:
|
|
2268
2158
|
// Should not happen
|
|
2269
2159
|
break;
|
|
@@ -2277,7 +2167,6 @@
|
|
|
2277
2167
|
material.color.convertSRGBToLinear();
|
|
2278
2168
|
material.polygonOffset = true;
|
|
2279
2169
|
material.polygonOffsetFactor = 1;
|
|
2280
|
-
|
|
2281
2170
|
if ( luminance !== 0 ) {
|
|
2282
2171
|
|
|
2283
2172
|
material.emissive.set( material.color ).multiplyScalar( luminance );
|
|
@@ -2295,8 +2184,9 @@
|
|
|
2295
2184
|
} );
|
|
2296
2185
|
edgeMaterial.userData.code = code;
|
|
2297
2186
|
edgeMaterial.name = name + ' - Edge';
|
|
2298
|
-
edgeMaterial.color.convertSRGBToLinear();
|
|
2187
|
+
edgeMaterial.color.convertSRGBToLinear();
|
|
2299
2188
|
|
|
2189
|
+
// This is the material used for conditional edges
|
|
2300
2190
|
edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial( {
|
|
2301
2191
|
fog: true,
|
|
2302
2192
|
transparent: isTransparent,
|
|
@@ -2315,12 +2205,11 @@
|
|
|
2315
2205
|
material.userData.edgeMaterial = edgeMaterial;
|
|
2316
2206
|
this.addMaterial( material );
|
|
2317
2207
|
return material;
|
|
2318
|
-
|
|
2319
2208
|
function parseLuminance( token ) {
|
|
2320
2209
|
|
|
2321
2210
|
// Returns success
|
|
2322
|
-
let lum;
|
|
2323
2211
|
|
|
2212
|
+
let lum;
|
|
2324
2213
|
if ( token.startsWith( 'LUMINANCE' ) ) {
|
|
2325
2214
|
|
|
2326
2215
|
lum = parseInt( token.substring( 9 ) );
|
|
@@ -2343,27 +2232,27 @@
|
|
|
2343
2232
|
}
|
|
2344
2233
|
|
|
2345
2234
|
}
|
|
2235
|
+
computeBuildingSteps( model ) {
|
|
2346
2236
|
|
|
2347
|
-
|
|
2237
|
+
// Sets userdata.buildingStep number in THREE.Group objects and userData.numBuildingSteps number in the root THREE.Group object.
|
|
2348
2238
|
|
|
2349
|
-
// Sets userdata.constructionStep number in THREE.Group objects and userData.numConstructionSteps number in the root THREE.Group object.
|
|
2350
2239
|
let stepNumber = 0;
|
|
2351
2240
|
model.traverse( c => {
|
|
2352
2241
|
|
|
2353
2242
|
if ( c.isGroup ) {
|
|
2354
2243
|
|
|
2355
|
-
if ( c.userData.
|
|
2244
|
+
if ( c.userData.startingBuildingStep ) {
|
|
2356
2245
|
|
|
2357
2246
|
stepNumber ++;
|
|
2358
2247
|
|
|
2359
2248
|
}
|
|
2360
2249
|
|
|
2361
|
-
c.userData.
|
|
2250
|
+
c.userData.buildingStep = stepNumber;
|
|
2362
2251
|
|
|
2363
2252
|
}
|
|
2364
2253
|
|
|
2365
2254
|
} );
|
|
2366
|
-
model.userData.
|
|
2255
|
+
model.userData.numBuildingSteps = stepNumber + 1;
|
|
2367
2256
|
|
|
2368
2257
|
}
|
|
2369
2258
|
|