super-three 0.133.4 → 0.136.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/build/three.js +2285 -1983
- package/build/three.min.js +1 -1
- package/build/three.module.js +5983 -5358
- package/examples/fonts/open-sans/open-sans-v15-cyrillic-ext_greek_greek-ext_cyrillic_latin_latin-ext_vietnamese-regular.woff +0 -0
- package/examples/fonts/open-sans/open-sans-v15-cyrillic-ext_greek_greek-ext_cyrillic_latin_latin-ext_vietnamese-regular.woff2 +0 -0
- package/examples/fonts/open-sans/open-sans.css +9 -0
- package/examples/fonts/tabler-icons/fonts/tabler-icons.eot +0 -0
- package/examples/fonts/tabler-icons/fonts/tabler-icons.svg +3966 -0
- package/examples/fonts/tabler-icons/fonts/tabler-icons.ttf +0 -0
- package/examples/fonts/tabler-icons/fonts/tabler-icons.woff +0 -0
- package/examples/fonts/tabler-icons/fonts/tabler-icons.woff2 +0 -0
- package/examples/fonts/tabler-icons/tabler-icons.min.css +4 -0
- package/examples/js/animation/CCDIKSolver.js +0 -1
- package/examples/js/animation/MMDPhysics.js +2 -4
- package/examples/js/cameras/CinematicCamera.js +2 -7
- package/examples/js/controls/ArcballControls.js +99 -72
- package/examples/js/controls/DragControls.js +7 -0
- package/examples/js/controls/OrbitControls.js +5 -36
- package/examples/js/controls/TrackballControls.js +3 -2
- package/examples/js/controls/TransformControls.js +24 -1
- package/examples/js/csm/CSM.js +2 -2
- package/examples/js/csm/CSMFrustum.js +133 -0
- package/examples/js/curves/CurveExtras.js +0 -2
- package/examples/js/effects/AsciiEffect.js +2 -9
- package/examples/js/exporters/GLTFExporter.js +148 -64
- package/examples/js/exporters/MMDExporter.js +1 -1
- package/examples/js/exporters/USDZExporter.js +45 -26
- package/examples/js/geometries/ConvexGeometry.js +1 -1
- package/examples/js/geometries/TeapotGeometry.js +0 -1
- package/examples/js/interactive/SelectionBox.js +2 -0
- package/examples/js/interactive/SelectionHelper.js +22 -7
- package/examples/js/lights/RectAreaLightUniformsLib.js +4 -0
- package/examples/js/lines/LineMaterial.js +58 -20
- package/examples/js/lines/LineSegments2.js +29 -24
- package/examples/js/loaders/3DMLoader.js +24 -11
- package/examples/js/loaders/3MFLoader.js +2 -2
- package/examples/js/loaders/AMFLoader.js +0 -2
- package/examples/js/loaders/BasisTextureLoader.js +1 -0
- package/examples/js/loaders/ColladaLoader.js +61 -4
- package/examples/js/loaders/EXRLoader.js +201 -272
- package/examples/js/loaders/FBXLoader.js +4 -5
- package/examples/js/loaders/GLTFLoader.js +98 -35
- package/examples/js/loaders/HDRCubeTextureLoader.js +0 -10
- package/examples/js/loaders/KTX2Loader.js +23 -2
- package/examples/js/loaders/KTXLoader.js +1 -1
- package/examples/js/loaders/LDrawLoader.js +1169 -901
- package/examples/js/loaders/LUT3dlLoader.js +19 -10
- package/examples/js/loaders/LUTCubeLoader.js +5 -4
- package/examples/js/loaders/LWOLoader.js +8 -6
- package/examples/js/loaders/LogLuvLoader.js +766 -0
- package/examples/js/loaders/MMDLoader.js +0 -1
- package/examples/js/loaders/NRRDLoader.js +9 -2
- package/examples/js/loaders/OBJLoader.js +0 -2
- package/examples/js/loaders/PLYLoader.js +33 -8
- package/examples/js/loaders/RGBELoader.js +8 -22
- package/examples/js/loaders/RGBMLoader.js +56 -6
- package/examples/js/loaders/SVGLoader.js +12 -6
- package/examples/js/loaders/TDSLoader.js +237 -271
- package/examples/js/loaders/VOXLoader.js +1 -0
- package/examples/js/loaders/VRMLLoader.js +11 -22
- package/examples/js/loaders/lwo/LWO2Parser.js +1 -0
- package/examples/js/loaders/lwo/LWO3Parser.js +4 -2
- package/examples/js/math/ConvexHull.js +7 -13
- package/examples/js/math/ImprovedNoise.js +1 -1
- package/examples/js/misc/GPUComputationRenderer.js +3 -1
- package/examples/js/misc/Volume.js +2 -2
- package/examples/js/modifiers/CurveModifier.js +8 -7
- package/examples/js/modifiers/EdgeSplitModifier.js +1 -1
- package/examples/js/modifiers/SimplifyModifier.js +1 -1
- package/examples/js/objects/Lensflare.js +2 -10
- package/examples/js/objects/MarchingCubes.js +42 -128
- package/examples/js/objects/Reflector.js +8 -13
- package/examples/js/objects/ReflectorForSSRPass.js +0 -10
- package/examples/js/objects/Refractor.js +8 -13
- package/examples/js/objects/Sky.js +1 -1
- package/examples/js/objects/Water.js +3 -15
- package/examples/js/objects/Water2.js +4 -7
- package/examples/js/postprocessing/GlitchPass.js +6 -5
- package/examples/js/postprocessing/SMAAPass.js +2 -9
- package/examples/js/postprocessing/SSAOPass.js +10 -21
- package/examples/js/postprocessing/SavePass.js +1 -5
- package/examples/js/renderers/CSS2DRenderer.js +4 -4
- package/examples/js/renderers/CSS3DRenderer.js +4 -4
- package/examples/js/shaders/ConvolutionShader.js +0 -1
- package/examples/js/shaders/DigitalGlitch.js +3 -3
- package/examples/js/shaders/FXAAShader.js +1 -1
- package/examples/js/shaders/FilmShader.js +1 -1
- package/examples/js/shaders/GammaCorrectionShader.js +1 -1
- package/examples/js/shaders/HorizontalBlurShader.js +1 -2
- package/examples/js/shaders/MMDToonShader.js +0 -1
- package/examples/js/shaders/SSAOShader.js +1 -1
- package/examples/js/shaders/SSRShader.js +1 -1
- package/examples/js/shaders/SSRrShader.js +1 -1
- package/examples/js/shaders/VerticalBlurShader.js +1 -2
- package/examples/js/utils/GeometryUtils.js +1 -1
- package/examples/jsm/animation/CCDIKSolver.js +0 -1
- package/examples/jsm/animation/MMDPhysics.js +1 -3
- package/examples/jsm/cameras/CinematicCamera.js +2 -5
- package/examples/jsm/{WebGL.js → capabilities/WebGL.js} +2 -2
- package/examples/jsm/{renderers/webgpu → capabilities}/WebGPU.js +1 -1
- package/examples/jsm/controls/ArcballControls.js +80 -77
- package/examples/jsm/controls/DragControls.js +7 -0
- package/examples/jsm/controls/OrbitControls.js +9 -51
- package/examples/jsm/controls/TrackballControls.js +1 -1
- package/examples/jsm/controls/TransformControls.js +24 -1
- package/examples/jsm/csm/CSM.js +3 -3
- package/examples/jsm/csm/{Frustum.js → CSMFrustum.js} +3 -3
- package/examples/jsm/curves/CurveExtras.js +0 -2
- package/examples/jsm/effects/AsciiEffect.js +2 -9
- package/examples/jsm/exporters/GLTFExporter.js +169 -99
- package/examples/jsm/exporters/MMDExporter.js +1 -1
- package/examples/jsm/exporters/USDZExporter.js +47 -26
- package/examples/jsm/geometries/ConvexGeometry.js +1 -1
- package/examples/jsm/geometries/TeapotGeometry.js +0 -1
- package/examples/jsm/interactive/SelectionBox.js +1 -0
- package/examples/jsm/interactive/SelectionHelper.js +19 -7
- package/examples/jsm/libs/flow.module.js +3338 -0
- package/examples/jsm/libs/lil-gui.module.min.js +8 -0
- package/examples/jsm/libs/rhino3dm/rhino3dm.wasm +0 -0
- package/examples/jsm/lights/RectAreaLightUniformsLib.js +7 -0
- package/examples/jsm/lines/LineMaterial.js +59 -23
- package/examples/jsm/lines/LineSegments2.js +22 -18
- package/examples/jsm/loaders/3DMLoader.js +18 -12
- package/examples/jsm/loaders/3MFLoader.js +2 -2
- package/examples/jsm/loaders/AMFLoader.js +0 -2
- package/examples/jsm/loaders/BasisTextureLoader.js +7 -0
- package/examples/jsm/loaders/ColladaLoader.js +61 -4
- package/examples/jsm/loaders/EXRLoader.js +200 -306
- package/examples/jsm/loaders/FBXLoader.js +4 -5
- package/examples/jsm/loaders/GLTFLoader.js +102 -40
- package/examples/jsm/loaders/HDRCubeTextureLoader.js +1 -17
- package/examples/jsm/loaders/KTX2Loader.js +30 -2
- package/examples/jsm/loaders/KTXLoader.js +1 -1
- package/examples/jsm/loaders/LDrawLoader.js +1159 -898
- package/examples/jsm/loaders/LUT3dlLoader.js +19 -12
- package/examples/jsm/loaders/LUTCubeLoader.js +5 -5
- package/examples/jsm/loaders/LWOLoader.js +8 -6
- package/examples/jsm/loaders/LogLuvLoader.js +606 -0
- package/examples/jsm/loaders/MMDLoader.js +0 -1
- package/examples/jsm/loaders/NRRDLoader.js +10 -2
- package/examples/jsm/loaders/OBJLoader.js +0 -2
- package/examples/jsm/loaders/PLYLoader.js +34 -8
- package/examples/jsm/loaders/RGBELoader.js +7 -28
- package/examples/jsm/loaders/RGBMLoader.js +62 -8
- package/examples/jsm/loaders/SVGLoader.js +15 -7
- package/examples/jsm/loaders/TDSLoader.js +236 -275
- package/examples/jsm/loaders/VOXLoader.js +1 -0
- package/examples/jsm/loaders/VRMLLoader.js +11 -23
- package/examples/jsm/loaders/lwo/LWO2Parser.js +1 -0
- package/examples/jsm/loaders/lwo/LWO3Parser.js +2 -2
- package/examples/jsm/math/ConvexHull.js +7 -13
- package/examples/jsm/math/ImprovedNoise.js +1 -1
- package/examples/jsm/misc/GPUComputationRenderer.js +3 -1
- package/examples/jsm/misc/Volume.js +2 -2
- package/examples/jsm/modifiers/CurveModifier.js +9 -8
- package/examples/jsm/modifiers/EdgeSplitModifier.js +1 -1
- package/examples/jsm/modifiers/SimplifyModifier.js +1 -1
- package/examples/jsm/node-editor/NodeEditor.js +455 -0
- package/examples/jsm/node-editor/accessors/NormalEditor.js +30 -0
- package/examples/jsm/node-editor/accessors/PositionEditor.js +30 -0
- package/examples/jsm/node-editor/accessors/UVEditor.js +26 -0
- package/examples/jsm/node-editor/display/BlendEditor.js +43 -0
- package/examples/jsm/node-editor/examples/animate-uv.json +1 -0
- package/examples/jsm/node-editor/examples/fake-top-light.json +1 -0
- package/examples/jsm/node-editor/examples/oscillator-color.json +1 -0
- package/examples/jsm/node-editor/examples/rim.json +1 -0
- package/examples/jsm/node-editor/inputs/ColorEditor.js +91 -0
- package/examples/jsm/node-editor/inputs/FloatEditor.js +24 -0
- package/examples/jsm/node-editor/inputs/SliderEditor.js +68 -0
- package/examples/jsm/node-editor/inputs/Vector2Editor.js +28 -0
- package/examples/jsm/node-editor/inputs/Vector3Editor.js +30 -0
- package/examples/jsm/node-editor/inputs/Vector4Editor.js +37 -0
- package/examples/jsm/node-editor/materials/StandardMaterialEditor.js +108 -0
- package/examples/jsm/node-editor/math/DotEditor.js +36 -0
- package/examples/jsm/node-editor/math/InvertEditor.js +38 -0
- package/examples/jsm/node-editor/math/LimiterEditor.js +48 -0
- package/examples/jsm/node-editor/math/NormalizeEditor.js +26 -0
- package/examples/jsm/node-editor/math/OperatorEditor.js +50 -0
- package/examples/jsm/node-editor/math/PowerEditor.js +34 -0
- package/examples/jsm/node-editor/math/TrigonometryEditor.js +39 -0
- package/examples/jsm/node-editor/procedural/CheckerEditor.js +26 -0
- package/examples/jsm/node-editor/utils/OscillatorEditor.js +42 -0
- package/examples/jsm/node-editor/utils/TimerEditor.js +57 -0
- package/examples/jsm/nodes/core/NodeBuilder.js +2 -2
- package/examples/jsm/nodes/materials/StandardNodeMaterial.js +1 -1
- package/examples/jsm/nodes/materials/nodes/StandardNode.js +7 -6
- package/examples/jsm/nodes/math/MathNode.js +12 -0
- package/examples/jsm/nodes/misc/BumpMapNode.js +1 -1
- package/examples/jsm/nodes/misc/TextureCubeUVNode.js +1 -4
- package/examples/jsm/nodes/utils/ColorSpaceNode.js +5 -177
- package/examples/jsm/objects/Lensflare.js +5 -16
- package/examples/jsm/objects/MarchingCubes.js +46 -152
- package/examples/jsm/objects/Reflector.js +8 -16
- package/examples/jsm/objects/ReflectorForSSRPass.js +0 -12
- package/examples/jsm/objects/Refractor.js +8 -16
- package/examples/jsm/objects/Sky.js +1 -1
- package/examples/jsm/objects/Water.js +3 -18
- package/examples/jsm/objects/Water2.js +4 -8
- package/examples/jsm/postprocessing/AdaptiveToneMappingPass.js +1 -1
- package/examples/jsm/postprocessing/AfterimagePass.js +1 -1
- package/examples/jsm/postprocessing/BloomPass.js +1 -1
- package/examples/jsm/postprocessing/BokehPass.js +1 -1
- package/examples/jsm/postprocessing/ClearPass.js +1 -1
- package/examples/jsm/postprocessing/CubeTexturePass.js +1 -1
- package/examples/jsm/postprocessing/DotScreenPass.js +1 -1
- package/examples/jsm/postprocessing/EffectComposer.js +3 -3
- package/examples/jsm/postprocessing/FilmPass.js +1 -1
- package/examples/jsm/postprocessing/GlitchPass.js +10 -7
- package/examples/jsm/postprocessing/HalftonePass.js +1 -1
- package/examples/jsm/postprocessing/MaskPass.js +1 -1
- package/examples/jsm/postprocessing/OutlinePass.js +1 -1
- package/examples/jsm/postprocessing/RenderPass.js +1 -1
- package/examples/jsm/postprocessing/SAOPass.js +2 -2
- package/examples/jsm/postprocessing/SMAAPass.js +3 -12
- package/examples/jsm/postprocessing/SSAARenderPass.js +1 -1
- package/examples/jsm/postprocessing/SSAOPass.js +15 -26
- package/examples/jsm/postprocessing/SSRPass.js +1 -1
- package/examples/jsm/postprocessing/SSRrPass.js +1 -1
- package/examples/jsm/postprocessing/SavePass.js +2 -4
- package/examples/jsm/postprocessing/ShaderPass.js +1 -1
- package/examples/jsm/postprocessing/TAARenderPass.js +1 -1
- package/examples/jsm/postprocessing/TexturePass.js +1 -1
- package/examples/jsm/postprocessing/UnrealBloomPass.js +1 -1
- package/examples/jsm/renderers/CSS2DRenderer.js +5 -4
- package/examples/jsm/renderers/CSS3DRenderer.js +5 -4
- package/examples/jsm/renderers/nodes/Nodes.js +17 -13
- package/examples/jsm/renderers/nodes/ShaderNode.js +229 -49
- package/examples/jsm/renderers/nodes/accessors/MaterialNode.js +6 -6
- package/examples/jsm/renderers/nodes/accessors/ModelViewProjectionNode.js +5 -5
- package/examples/jsm/renderers/nodes/accessors/NormalNode.js +14 -3
- package/examples/jsm/renderers/nodes/accessors/PointUVNode.js +3 -3
- package/examples/jsm/renderers/nodes/accessors/PositionNode.js +15 -5
- package/examples/jsm/renderers/nodes/accessors/SkinningNode.js +107 -0
- package/examples/jsm/renderers/nodes/accessors/UVNode.js +7 -5
- package/examples/jsm/renderers/nodes/core/ArrayInputNode.js +3 -3
- package/examples/jsm/renderers/nodes/core/AttributeNode.js +6 -0
- package/examples/jsm/renderers/nodes/core/BypassNode.js +38 -0
- package/examples/jsm/renderers/nodes/core/CodeNode.js +3 -3
- package/examples/jsm/renderers/nodes/core/ContextNode.js +4 -19
- package/examples/jsm/renderers/nodes/core/ExpressionNode.js +13 -2
- package/examples/jsm/renderers/nodes/core/FunctionNode.js +19 -132
- package/examples/jsm/renderers/nodes/core/InputNode.js +13 -3
- package/examples/jsm/renderers/nodes/core/Node.js +32 -10
- package/examples/jsm/renderers/nodes/core/NodeBuilder.js +146 -128
- package/examples/jsm/renderers/nodes/core/NodeFunction.js +22 -0
- package/examples/jsm/renderers/nodes/core/NodeFunctionInput.js +4 -4
- package/examples/jsm/renderers/nodes/core/NodeKeywords.js +18 -179
- package/examples/jsm/renderers/nodes/core/NodeParser.js +11 -0
- package/examples/jsm/renderers/nodes/core/NodeVar.js +2 -2
- package/examples/jsm/renderers/nodes/core/PropertyNode.js +14 -2
- package/examples/jsm/renderers/nodes/core/TempNode.js +10 -13
- package/examples/jsm/renderers/nodes/core/VarNode.js +12 -7
- package/examples/jsm/renderers/nodes/core/VaryNode.js +23 -8
- package/examples/jsm/renderers/nodes/core/constants.js +2 -0
- package/examples/jsm/renderers/nodes/display/ColorSpaceNode.js +43 -63
- package/examples/jsm/renderers/nodes/display/NormalMapNode.js +21 -22
- package/examples/jsm/renderers/nodes/functions/BSDFs.js +64 -101
- package/examples/jsm/renderers/nodes/functions/PhysicalMaterialFunctions.js +27 -0
- package/examples/jsm/renderers/nodes/inputs/BufferNode.js +25 -0
- package/examples/jsm/renderers/nodes/inputs/IntNode.js +17 -0
- package/examples/jsm/renderers/nodes/inputs/TextureNode.js +13 -10
- package/examples/jsm/renderers/nodes/lights/LightContextNode.js +20 -14
- package/examples/jsm/renderers/nodes/lights/LightNode.js +32 -36
- package/examples/jsm/renderers/nodes/math/CondNode.js +60 -0
- package/examples/jsm/renderers/nodes/math/MathNode.js +91 -37
- package/examples/jsm/renderers/nodes/math/OperatorNode.js +124 -31
- package/examples/jsm/renderers/nodes/parsers/GLSLNodeFunction.js +137 -0
- package/examples/jsm/renderers/nodes/parsers/GLSLNodeParser.js +14 -0
- package/examples/jsm/renderers/nodes/parsers/WGSLNodeFunction.js +89 -0
- package/examples/jsm/renderers/nodes/parsers/WGSLNodeParser.js +14 -0
- package/examples/jsm/renderers/nodes/procedural/CheckerNode.js +7 -9
- package/examples/jsm/renderers/nodes/utils/ArrayElementNode.js +31 -0
- package/examples/jsm/renderers/nodes/utils/ConvertNode.js +33 -0
- package/examples/jsm/renderers/nodes/utils/JoinNode.js +7 -7
- package/examples/jsm/renderers/nodes/utils/OscNode.js +58 -0
- package/examples/jsm/renderers/nodes/utils/SplitNode.js +18 -8
- package/examples/jsm/renderers/nodes/utils/SpriteSheetUVNode.js +7 -7
- package/examples/jsm/renderers/nodes/utils/TimerNode.js +1 -1
- package/examples/jsm/renderers/webgl/nodes/SlotNode.js +22 -0
- package/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js +192 -95
- package/examples/jsm/renderers/webgl/nodes/WebGLNodes.js +2 -2
- package/examples/jsm/renderers/webgl/nodes/WebGLPhysicalContextNode.js +2 -2
- package/examples/jsm/renderers/webgpu/WebGPUBackground.js +1 -1
- package/examples/jsm/renderers/webgpu/WebGPUBindings.js +10 -9
- package/examples/jsm/renderers/webgpu/WebGPUComputePipelines.js +2 -4
- package/examples/jsm/renderers/webgpu/WebGPUObjects.js +1 -1
- package/examples/jsm/renderers/webgpu/WebGPUProgrammableStage.js +2 -4
- package/examples/jsm/renderers/webgpu/WebGPURenderPipeline.js +15 -23
- package/examples/jsm/renderers/webgpu/WebGPURenderPipelines.js +44 -65
- package/examples/jsm/renderers/webgpu/WebGPURenderer.js +13 -31
- package/examples/jsm/renderers/webgpu/WebGPUTextureUtils.js +61 -28
- package/examples/jsm/renderers/webgpu/WebGPUTextures.js +35 -29
- package/examples/jsm/renderers/webgpu/constants.js +2 -2
- package/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js +459 -95
- package/examples/jsm/renderers/webgpu/nodes/WebGPUNodes.js +1 -1
- package/examples/jsm/shaders/ConvolutionShader.js +0 -1
- package/examples/jsm/shaders/DigitalGlitch.js +3 -3
- package/examples/jsm/shaders/FXAAShader.js +1 -1
- package/examples/jsm/shaders/FilmShader.js +1 -1
- package/examples/jsm/shaders/GammaCorrectionShader.js +1 -1
- package/examples/jsm/shaders/HorizontalBlurShader.js +1 -2
- package/examples/jsm/shaders/MMDToonShader.js +0 -1
- package/examples/jsm/shaders/SSAOShader.js +1 -1
- package/examples/jsm/shaders/SSRShader.js +1 -1
- package/examples/jsm/shaders/SSRrShader.js +1 -1
- package/examples/jsm/shaders/VerticalBlurShader.js +1 -2
- package/examples/jsm/utils/GeometryUtils.js +1 -1
- package/examples/jsm/utils/LDrawUtils.js +195 -0
- package/examples/jsm/utils/WorkerPool.js +11 -11
- package/examples/jsm/webxr/OculusHandPointerModel.js +6 -6
- package/examples/jsm/webxr/VRButton.js +24 -0
- package/examples/jsm/webxr/XREstimatedLight.js +2 -0
- package/package.json +27 -18
- package/src/Three.Legacy.js +18 -0
- package/src/Three.js +1 -3
- package/src/animation/AnimationMixer.js +1 -0
- package/src/cameras/CubeCamera.js +2 -0
- package/src/cameras/StereoCamera.js +8 -7
- package/src/constants.js +3 -23
- package/src/core/Layers.js +7 -1
- package/src/core/Object3D.js +3 -1
- package/src/extras/ImageUtils.js +63 -0
- package/src/extras/PMREMGenerator.js +49 -185
- package/src/extras/core/Interpolations.js +1 -1
- package/src/geometries/LatheGeometry.js +70 -47
- package/src/helpers/CameraHelper.js +1 -1
- package/src/loaders/FileLoader.js +98 -144
- package/src/loaders/ImageLoader.js +9 -4
- package/src/loaders/LoaderUtils.js +26 -0
- package/src/loaders/MaterialLoader.js +8 -5
- package/src/loaders/ObjectLoader.js +2 -0
- package/src/materials/Material.js +8 -8
- package/src/materials/MeshPhysicalMaterial.js +20 -14
- package/src/math/Color.js +1 -39
- package/src/math/MathUtils.js +5 -16
- package/src/math/Quaternion.js +1 -1
- package/src/math/Ray.js +2 -2
- package/src/math/Sphere.js +10 -1
- package/src/objects/Skeleton.js +1 -0
- package/src/renderers/WebGLCubeRenderTarget.js +0 -2
- package/src/renderers/WebGLMultisampleRenderTarget.js +7 -1
- package/src/renderers/WebGLRenderer.js +106 -199
- package/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js +2 -2
- package/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +2 -24
- package/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js +0 -2
- package/src/renderers/shaders/ShaderChunk/encodings_pars_fragment.glsl.js +0 -78
- package/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js +0 -1
- package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +0 -2
- package/src/renderers/shaders/ShaderChunk/gradientmap_pars_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +19 -6
- package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +28 -2
- package/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js +10 -3
- package/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js +1 -2
- package/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +9 -8
- package/src/renderers/shaders/ShaderLib/background.glsl.js +1 -3
- package/src/renderers/shaders/ShaderLib/equirect.glsl.js +1 -3
- package/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +1 -1
- package/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js +1 -2
- package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +23 -5
- package/src/renderers/shaders/ShaderLib/vsm.glsl.js +2 -1
- package/src/renderers/shaders/ShaderLib.js +8 -6
- package/src/renderers/shaders/UniformsLib.js +1 -2
- package/src/renderers/webgl/WebGLCapabilities.js +0 -2
- package/src/renderers/webgl/WebGLCubeMaps.js +0 -4
- package/src/renderers/webgl/WebGLCubeUVMaps.js +29 -16
- package/src/renderers/webgl/WebGLExtensions.js +1 -0
- package/src/renderers/webgl/WebGLMaterials.js +27 -15
- package/src/renderers/webgl/WebGLMorphtargets.js +13 -0
- package/src/renderers/webgl/WebGLProgram.js +12 -37
- package/src/renderers/webgl/WebGLPrograms.js +192 -70
- package/src/renderers/webgl/WebGLRenderLists.js +4 -14
- package/src/renderers/webgl/WebGLShaderCache.js +120 -0
- package/src/renderers/webgl/WebGLShadowMap.js +14 -5
- package/src/renderers/webgl/WebGLState.js +157 -17
- package/src/renderers/webgl/WebGLTextures.js +442 -83
- package/src/renderers/webgl/WebGLUniforms.js +45 -1
- package/src/renderers/webgl/WebGLUtils.js +86 -28
- package/src/renderers/webxr/WebXRManager.js +77 -109
- package/src/scenes/Scene.js +1 -1
- package/src/textures/DataTexture.js +0 -2
- package/src/textures/DataTexture2DArray.js +0 -2
- package/src/textures/DataTexture3D.js +0 -2
- package/src/textures/FramebufferTexture.js +25 -0
- package/src/textures/Texture.js +8 -1
- package/src/textures/VideoTexture.js +1 -3
- package/examples/js/WebGL.js +0 -90
- package/examples/js/controls/DeviceOrientationControls.js +0 -147
- package/examples/js/libs/dat.gui.min.js +0 -14
- package/examples/js/utils/RoughnessMipmapper.js +0 -278
- package/examples/jsm/controls/DeviceOrientationControls.js +0 -153
- package/examples/jsm/libs/dat.gui.module.js +0 -3575
- package/examples/jsm/libs/glslang.js +0 -78
- package/examples/jsm/libs/glslang.wasm +0 -0
- package/examples/jsm/renderers/nodes/consts/MathConsts.js +0 -7
- package/examples/jsm/renderers/nodes/core/ConstNode.js +0 -39
- package/examples/jsm/renderers/nodes/core/NodeSlot.js +0 -13
- package/examples/jsm/renderers/nodes/core/StructNode.js +0 -80
- package/examples/jsm/renderers/nodes/core/StructVarNode.js +0 -75
- package/examples/jsm/renderers/nodes/functions/EncodingFunctions.js +0 -99
- package/examples/jsm/renderers/nodes/functions/MathFunctions.js +0 -47
- package/examples/jsm/renderers/webgpu/nodes/ShaderLib.js +0 -152
- package/examples/jsm/utils/RoughnessMipmapper.js +0 -300
- package/src/extras/objects/ImmediateRenderObject.js +0 -31
|
@@ -7,14 +7,15 @@ import {
|
|
|
7
7
|
LineBasicMaterial,
|
|
8
8
|
LineSegments,
|
|
9
9
|
Loader,
|
|
10
|
+
Matrix3,
|
|
10
11
|
Matrix4,
|
|
11
12
|
Mesh,
|
|
12
|
-
MeshPhongMaterial,
|
|
13
13
|
MeshStandardMaterial,
|
|
14
14
|
ShaderMaterial,
|
|
15
15
|
UniformsLib,
|
|
16
16
|
UniformsUtils,
|
|
17
|
-
Vector3
|
|
17
|
+
Vector3,
|
|
18
|
+
Ray
|
|
18
19
|
} from 'three';
|
|
19
20
|
|
|
20
21
|
// Special surface finish tag types.
|
|
@@ -168,16 +169,45 @@ class LDrawConditionalLineMaterial extends ShaderMaterial {
|
|
|
168
169
|
|
|
169
170
|
}
|
|
170
171
|
|
|
171
|
-
function
|
|
172
|
+
function generateFaceNormals( faces ) {
|
|
172
173
|
|
|
174
|
+
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
175
|
+
|
|
176
|
+
const face = faces[ i ];
|
|
177
|
+
const vertices = face.vertices;
|
|
178
|
+
const v0 = vertices[ 0 ];
|
|
179
|
+
const v1 = vertices[ 1 ];
|
|
180
|
+
const v2 = vertices[ 2 ];
|
|
181
|
+
|
|
182
|
+
_tempVec0.subVectors( v1, v0 );
|
|
183
|
+
_tempVec1.subVectors( v2, v1 );
|
|
184
|
+
face.faceNormal = new Vector3()
|
|
185
|
+
.crossVectors( _tempVec0, _tempVec1 )
|
|
186
|
+
.normalize();
|
|
187
|
+
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const _ray = new Ray();
|
|
193
|
+
function smoothNormals( faces, lineSegments, checkSubSegments = false ) {
|
|
194
|
+
|
|
195
|
+
// NOTE: 1e2 is pretty coarse but was chosen to quantize the resulting value because
|
|
196
|
+
// it allows edges to be smoothed as expected (see minifig arms).
|
|
197
|
+
// --
|
|
198
|
+
// And the vector values are initialize multiplied by 1 + 1e-10 to account for floating
|
|
199
|
+
// point errors on vertices along quantization boundaries. Ie after matrix multiplication
|
|
200
|
+
// vertices that should be merged might be set to "1.7" and "1.6999..." meaning they won't
|
|
201
|
+
// get merged. This added epsilon attempts to push these error values to the same quantized
|
|
202
|
+
// value for the sake of hashing. See "AT-ST mini" dishes. See mrdoob/three#23169.
|
|
203
|
+
|
|
204
|
+
const hashMultiplier = ( 1 + 1e-10 ) * 1e2;
|
|
173
205
|
function hashVertex( v ) {
|
|
174
206
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const y = ~ ~ ( v.y * 1e2 );
|
|
180
|
-
const z = ~ ~ ( v.z * 1e2 );
|
|
207
|
+
const x = ~ ~ ( v.x * hashMultiplier );
|
|
208
|
+
const y = ~ ~ ( v.y * hashMultiplier );
|
|
209
|
+
const z = ~ ~ ( v.z * hashMultiplier );
|
|
210
|
+
|
|
181
211
|
return `${ x },${ y },${ z }`;
|
|
182
212
|
|
|
183
213
|
}
|
|
@@ -188,7 +218,27 @@ function smoothNormals( faces, lineSegments ) {
|
|
|
188
218
|
|
|
189
219
|
}
|
|
190
220
|
|
|
221
|
+
// converts the two vertices to a ray with a normalized direction and origin of 0, 0, 0 projected
|
|
222
|
+
// onto the original line.
|
|
223
|
+
function toNormalizedRay( v0, v1, targetRay ) {
|
|
224
|
+
|
|
225
|
+
targetRay.direction.subVectors( v1, v0 ).normalize();
|
|
226
|
+
|
|
227
|
+
const scalar = v0.dot( targetRay.direction );
|
|
228
|
+
targetRay.origin.copy( v0 ).addScaledVector( targetRay.direction, - scalar );
|
|
229
|
+
|
|
230
|
+
return targetRay;
|
|
231
|
+
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function hashRay( ray ) {
|
|
235
|
+
|
|
236
|
+
return hashEdge( ray.origin, ray.direction );
|
|
237
|
+
|
|
238
|
+
}
|
|
239
|
+
|
|
191
240
|
const hardEdges = new Set();
|
|
241
|
+
const hardEdgeRays = new Map();
|
|
192
242
|
const halfEdgeList = {};
|
|
193
243
|
const normals = [];
|
|
194
244
|
|
|
@@ -202,6 +252,43 @@ function smoothNormals( faces, lineSegments ) {
|
|
|
202
252
|
hardEdges.add( hashEdge( v0, v1 ) );
|
|
203
253
|
hardEdges.add( hashEdge( v1, v0 ) );
|
|
204
254
|
|
|
255
|
+
// only generate the hard edge ray map if we're checking subsegments because it's more expensive to check
|
|
256
|
+
// and requires more memory.
|
|
257
|
+
if ( checkSubSegments ) {
|
|
258
|
+
|
|
259
|
+
// add both ray directions to the map
|
|
260
|
+
const ray = toNormalizedRay( v0, v1, new Ray() );
|
|
261
|
+
const rh1 = hashRay( ray );
|
|
262
|
+
if ( ! hardEdgeRays.has( rh1 ) ) {
|
|
263
|
+
|
|
264
|
+
toNormalizedRay( v1, v0, ray );
|
|
265
|
+
const rh2 = hashRay( ray );
|
|
266
|
+
|
|
267
|
+
const info = {
|
|
268
|
+
ray,
|
|
269
|
+
distances: [],
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
hardEdgeRays.set( rh1, info );
|
|
273
|
+
hardEdgeRays.set( rh2, info );
|
|
274
|
+
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// store both segments ends in min, max order in the distances array to check if a face edge is a
|
|
278
|
+
// subsegment later.
|
|
279
|
+
const info = hardEdgeRays.get( rh1 );
|
|
280
|
+
let d0 = info.ray.direction.dot( v0 );
|
|
281
|
+
let d1 = info.ray.direction.dot( v1 );
|
|
282
|
+
if ( d0 > d1 ) {
|
|
283
|
+
|
|
284
|
+
[ d0, d1 ] = [ d1, d0 ];
|
|
285
|
+
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
info.distances.push( d0, d1 );
|
|
289
|
+
|
|
290
|
+
}
|
|
291
|
+
|
|
205
292
|
}
|
|
206
293
|
|
|
207
294
|
// track the half edges associated with each triangle
|
|
@@ -219,7 +306,53 @@ function smoothNormals( faces, lineSegments ) {
|
|
|
219
306
|
const hash = hashEdge( v0, v1 );
|
|
220
307
|
|
|
221
308
|
// don't add the triangle if the edge is supposed to be hard
|
|
222
|
-
if ( hardEdges.has( hash ) )
|
|
309
|
+
if ( hardEdges.has( hash ) ) {
|
|
310
|
+
|
|
311
|
+
continue;
|
|
312
|
+
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// if checking subsegments then check to see if this edge lies on a hard edge ray and whether its within any ray bounds
|
|
316
|
+
if ( checkSubSegments ) {
|
|
317
|
+
|
|
318
|
+
toNormalizedRay( v0, v1, _ray );
|
|
319
|
+
|
|
320
|
+
const rayHash = hashRay( _ray );
|
|
321
|
+
if ( hardEdgeRays.has( rayHash ) ) {
|
|
322
|
+
|
|
323
|
+
const info = hardEdgeRays.get( rayHash );
|
|
324
|
+
const { ray, distances } = info;
|
|
325
|
+
let d0 = ray.direction.dot( v0 );
|
|
326
|
+
let d1 = ray.direction.dot( v1 );
|
|
327
|
+
|
|
328
|
+
if ( d0 > d1 ) {
|
|
329
|
+
|
|
330
|
+
[ d0, d1 ] = [ d1, d0 ];
|
|
331
|
+
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// return early if the face edge is found to be a subsegment of a line edge meaning the edge will have "hard" normals
|
|
335
|
+
let found = false;
|
|
336
|
+
for ( let i = 0, l = distances.length; i < l; i += 2 ) {
|
|
337
|
+
|
|
338
|
+
if ( d0 >= distances[ i ] && d1 <= distances[ i + 1 ] ) {
|
|
339
|
+
|
|
340
|
+
found = true;
|
|
341
|
+
break;
|
|
342
|
+
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if ( found ) {
|
|
348
|
+
|
|
349
|
+
continue;
|
|
350
|
+
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
}
|
|
223
356
|
|
|
224
357
|
const info = {
|
|
225
358
|
index: index,
|
|
@@ -463,6 +596,12 @@ class LineParser {
|
|
|
463
596
|
|
|
464
597
|
}
|
|
465
598
|
|
|
599
|
+
getVector() {
|
|
600
|
+
|
|
601
|
+
return new Vector3( parseFloat( this.getToken() ), parseFloat( this.getToken() ), parseFloat( this.getToken() ) );
|
|
602
|
+
|
|
603
|
+
}
|
|
604
|
+
|
|
466
605
|
getRemainingString() {
|
|
467
606
|
|
|
468
607
|
return this.line.substring( this.currentCharIndex, this.lineLength );
|
|
@@ -489,1343 +628,1454 @@ class LineParser {
|
|
|
489
628
|
|
|
490
629
|
}
|
|
491
630
|
|
|
492
|
-
class
|
|
631
|
+
class LDrawParsedCache {
|
|
493
632
|
|
|
494
633
|
constructor( loader ) {
|
|
495
634
|
|
|
496
|
-
this.cache = {};
|
|
497
635
|
this.loader = loader;
|
|
636
|
+
this.cache = {};
|
|
498
637
|
|
|
499
638
|
}
|
|
500
639
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
this.cache[ key.toLowerCase() ] = contents;
|
|
640
|
+
cloneResult( original ) {
|
|
504
641
|
|
|
505
|
-
|
|
642
|
+
const result = {};
|
|
506
643
|
|
|
507
|
-
|
|
644
|
+
// vertices are transformed and normals computed before being converted to geometry
|
|
645
|
+
// so these pieces must be cloned.
|
|
646
|
+
result.faces = original.faces.map( face => {
|
|
508
647
|
|
|
509
|
-
|
|
510
|
-
|
|
648
|
+
return {
|
|
649
|
+
colorCode: face.colorCode,
|
|
650
|
+
material: face.material,
|
|
651
|
+
vertices: face.vertices.map( v => v.clone() ),
|
|
652
|
+
normals: face.normals.map( () => null ),
|
|
653
|
+
faceNormal: null
|
|
654
|
+
};
|
|
511
655
|
|
|
512
|
-
|
|
656
|
+
} );
|
|
513
657
|
|
|
514
|
-
|
|
658
|
+
result.conditionalSegments = original.conditionalSegments.map( face => {
|
|
515
659
|
|
|
516
|
-
|
|
660
|
+
return {
|
|
661
|
+
colorCode: face.colorCode,
|
|
662
|
+
material: face.material,
|
|
663
|
+
vertices: face.vertices.map( v => v.clone() ),
|
|
664
|
+
controlPoints: face.controlPoints.map( v => v.clone() )
|
|
665
|
+
};
|
|
517
666
|
|
|
518
|
-
|
|
519
|
-
let locationState = FILE_LOCATION_AS_IS;
|
|
520
|
-
while ( locationState !== FILE_LOCATION_NOT_FOUND ) {
|
|
667
|
+
} );
|
|
521
668
|
|
|
522
|
-
|
|
523
|
-
switch ( locationState ) {
|
|
669
|
+
result.lineSegments = original.lineSegments.map( face => {
|
|
524
670
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
671
|
+
return {
|
|
672
|
+
colorCode: face.colorCode,
|
|
673
|
+
material: face.material,
|
|
674
|
+
vertices: face.vertices.map( v => v.clone() )
|
|
675
|
+
};
|
|
528
676
|
|
|
529
|
-
|
|
530
|
-
subobjectURL = 'parts/' + subobjectURL;
|
|
531
|
-
locationState = locationState + 1;
|
|
532
|
-
break;
|
|
677
|
+
} );
|
|
533
678
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
679
|
+
// none if this is subsequently modified
|
|
680
|
+
result.type = original.type;
|
|
681
|
+
result.category = original.category;
|
|
682
|
+
result.keywords = original.keywords;
|
|
683
|
+
result.subobjects = original.subobjects;
|
|
684
|
+
result.totalFaces = original.totalFaces;
|
|
685
|
+
result.startingConstructionStep = original.startingConstructionStep;
|
|
686
|
+
result.materials = original.materials;
|
|
687
|
+
return result;
|
|
538
688
|
|
|
539
|
-
|
|
540
|
-
subobjectURL = 'models/' + subobjectURL;
|
|
541
|
-
locationState = locationState + 1;
|
|
542
|
-
break;
|
|
689
|
+
}
|
|
543
690
|
|
|
544
|
-
|
|
545
|
-
subobjectURL = fileName.substring( 0, fileName.lastIndexOf( '/' ) + 1 ) + subobjectURL;
|
|
546
|
-
locationState = locationState + 1;
|
|
547
|
-
break;
|
|
691
|
+
async fetchData( fileName ) {
|
|
548
692
|
|
|
549
|
-
|
|
693
|
+
let triedLowerCase = false;
|
|
694
|
+
let locationState = FILE_LOCATION_AS_IS;
|
|
695
|
+
while ( locationState !== FILE_LOCATION_NOT_FOUND ) {
|
|
550
696
|
|
|
551
|
-
|
|
697
|
+
let subobjectURL = fileName;
|
|
698
|
+
switch ( locationState ) {
|
|
552
699
|
|
|
553
|
-
|
|
554
|
-
|
|
700
|
+
case FILE_LOCATION_AS_IS:
|
|
701
|
+
locationState = locationState + 1;
|
|
702
|
+
break;
|
|
555
703
|
|
|
556
|
-
|
|
704
|
+
case FILE_LOCATION_TRY_PARTS:
|
|
705
|
+
subobjectURL = 'parts/' + subobjectURL;
|
|
706
|
+
locationState = locationState + 1;
|
|
707
|
+
break;
|
|
557
708
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
locationState = FILE_LOCATION_AS_IS;
|
|
709
|
+
case FILE_LOCATION_TRY_P:
|
|
710
|
+
subobjectURL = 'p/' + subobjectURL;
|
|
711
|
+
locationState = locationState + 1;
|
|
712
|
+
break;
|
|
563
713
|
|
|
564
|
-
|
|
714
|
+
case FILE_LOCATION_TRY_MODELS:
|
|
715
|
+
subobjectURL = 'models/' + subobjectURL;
|
|
716
|
+
locationState = locationState + 1;
|
|
717
|
+
break;
|
|
565
718
|
|
|
566
|
-
|
|
719
|
+
case FILE_LOCATION_TRY_RELATIVE:
|
|
720
|
+
subobjectURL = fileName.substring( 0, fileName.lastIndexOf( '/' ) + 1 ) + subobjectURL;
|
|
721
|
+
locationState = locationState + 1;
|
|
722
|
+
break;
|
|
567
723
|
|
|
568
|
-
|
|
724
|
+
case FILE_LOCATION_TRY_ABSOLUTE:
|
|
569
725
|
|
|
570
|
-
|
|
571
|
-
const fileLoader = new FileLoader( loader.manager );
|
|
572
|
-
fileLoader.setPath( loader.partsLibraryPath );
|
|
573
|
-
fileLoader.setRequestHeader( loader.requestHeader );
|
|
574
|
-
fileLoader.setWithCredentials( loader.withCredentials );
|
|
726
|
+
if ( triedLowerCase ) {
|
|
575
727
|
|
|
576
|
-
|
|
728
|
+
// Try absolute path
|
|
729
|
+
locationState = FILE_LOCATION_NOT_FOUND;
|
|
577
730
|
|
|
578
|
-
|
|
579
|
-
this.setData( fileName, text );
|
|
580
|
-
resolve( text );
|
|
581
|
-
return;
|
|
731
|
+
} else {
|
|
582
732
|
|
|
583
|
-
|
|
733
|
+
// Next attempt is lower case
|
|
734
|
+
fileName = fileName.toLowerCase();
|
|
735
|
+
subobjectURL = fileName;
|
|
736
|
+
triedLowerCase = true;
|
|
737
|
+
locationState = FILE_LOCATION_AS_IS;
|
|
584
738
|
|
|
585
|
-
|
|
739
|
+
}
|
|
586
740
|
|
|
587
|
-
|
|
741
|
+
break;
|
|
588
742
|
|
|
589
743
|
}
|
|
590
744
|
|
|
591
|
-
|
|
745
|
+
const loader = this.loader;
|
|
746
|
+
const fileLoader = new FileLoader( loader.manager );
|
|
747
|
+
fileLoader.setPath( loader.partsLibraryPath );
|
|
748
|
+
fileLoader.setRequestHeader( loader.requestHeader );
|
|
749
|
+
fileLoader.setWithCredentials( loader.withCredentials );
|
|
592
750
|
|
|
593
|
-
|
|
751
|
+
try {
|
|
594
752
|
|
|
595
|
-
|
|
753
|
+
const text = await fileLoader.loadAsync( subobjectURL );
|
|
754
|
+
return text;
|
|
596
755
|
|
|
597
|
-
|
|
756
|
+
} catch {
|
|
598
757
|
|
|
599
|
-
|
|
758
|
+
continue;
|
|
600
759
|
|
|
601
|
-
|
|
760
|
+
}
|
|
602
761
|
|
|
603
|
-
|
|
762
|
+
}
|
|
604
763
|
|
|
605
|
-
|
|
764
|
+
throw new Error( 'LDrawLoader: Subobject "' + fileName + '" could not be loaded.' );
|
|
606
765
|
|
|
607
766
|
}
|
|
608
767
|
|
|
609
|
-
|
|
768
|
+
parse( text ) {
|
|
610
769
|
|
|
611
|
-
|
|
770
|
+
const loader = this.loader;
|
|
612
771
|
|
|
613
|
-
|
|
772
|
+
// final results
|
|
773
|
+
const faces = [];
|
|
774
|
+
const lineSegments = [];
|
|
775
|
+
const conditionalSegments = [];
|
|
776
|
+
const subobjects = [];
|
|
777
|
+
const materials = {};
|
|
614
778
|
|
|
615
|
-
|
|
779
|
+
const getLocalMaterial = colorCode => {
|
|
616
780
|
|
|
617
|
-
|
|
781
|
+
return colorCode in materials ? materials[ colorCode ] : null;
|
|
618
782
|
|
|
619
|
-
|
|
783
|
+
};
|
|
620
784
|
|
|
621
|
-
|
|
622
|
-
|
|
785
|
+
let type = 'Model';
|
|
786
|
+
let category = null;
|
|
787
|
+
let keywords = null;
|
|
788
|
+
let totalFaces = 0;
|
|
623
789
|
|
|
624
|
-
|
|
625
|
-
|
|
790
|
+
// split into lines
|
|
791
|
+
if ( text.indexOf( '\r\n' ) !== - 1 ) {
|
|
626
792
|
|
|
627
|
-
|
|
793
|
+
// This is faster than String.split with regex that splits on both
|
|
794
|
+
text = text.replace( /\r\n/g, '\n' );
|
|
628
795
|
|
|
629
|
-
|
|
796
|
+
}
|
|
630
797
|
|
|
631
|
-
|
|
798
|
+
const lines = text.split( '\n' );
|
|
799
|
+
const numLines = lines.length;
|
|
632
800
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
801
|
+
let parsingEmbeddedFiles = false;
|
|
802
|
+
let currentEmbeddedFileName = null;
|
|
803
|
+
let currentEmbeddedText = null;
|
|
636
804
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
let numGroupVerts = 0;
|
|
642
|
-
let offset = 0;
|
|
805
|
+
let bfcCertified = false;
|
|
806
|
+
let bfcCCW = true;
|
|
807
|
+
let bfcInverted = false;
|
|
808
|
+
let bfcCull = true;
|
|
643
809
|
|
|
644
|
-
|
|
810
|
+
let startingConstructionStep = false;
|
|
645
811
|
|
|
646
|
-
|
|
647
|
-
let
|
|
648
|
-
if ( vertices.length === 4 ) {
|
|
812
|
+
// Parse all line commands
|
|
813
|
+
for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) {
|
|
649
814
|
|
|
650
|
-
|
|
651
|
-
quadArray[ 1 ] = vertices[ 1 ];
|
|
652
|
-
quadArray[ 2 ] = vertices[ 2 ];
|
|
653
|
-
quadArray[ 3 ] = vertices[ 0 ];
|
|
654
|
-
quadArray[ 4 ] = vertices[ 2 ];
|
|
655
|
-
quadArray[ 5 ] = vertices[ 3 ];
|
|
656
|
-
vertices = quadArray;
|
|
815
|
+
const line = lines[ lineIndex ];
|
|
657
816
|
|
|
658
|
-
|
|
817
|
+
if ( line.length === 0 ) continue;
|
|
659
818
|
|
|
660
|
-
|
|
819
|
+
if ( parsingEmbeddedFiles ) {
|
|
661
820
|
|
|
662
|
-
|
|
663
|
-
const index = offset + j * 3;
|
|
664
|
-
positions[ index + 0 ] = v.x;
|
|
665
|
-
positions[ index + 1 ] = v.y;
|
|
666
|
-
positions[ index + 2 ] = v.z;
|
|
821
|
+
if ( line.startsWith( '0 FILE ' ) ) {
|
|
667
822
|
|
|
668
|
-
|
|
823
|
+
// Save previous embedded file in the cache
|
|
824
|
+
this.setData( currentEmbeddedFileName, currentEmbeddedText );
|
|
669
825
|
|
|
670
|
-
|
|
826
|
+
// New embedded text file
|
|
827
|
+
currentEmbeddedFileName = line.substring( 7 );
|
|
828
|
+
currentEmbeddedText = '';
|
|
671
829
|
|
|
672
|
-
|
|
673
|
-
if ( elemNormals.length === 4 ) {
|
|
830
|
+
} else {
|
|
674
831
|
|
|
675
|
-
|
|
676
|
-
quadArray[ 1 ] = elemNormals[ 1 ];
|
|
677
|
-
quadArray[ 2 ] = elemNormals[ 2 ];
|
|
678
|
-
quadArray[ 3 ] = elemNormals[ 0 ];
|
|
679
|
-
quadArray[ 4 ] = elemNormals[ 2 ];
|
|
680
|
-
quadArray[ 5 ] = elemNormals[ 3 ];
|
|
681
|
-
elemNormals = quadArray;
|
|
832
|
+
currentEmbeddedText += line + '\n';
|
|
682
833
|
|
|
683
|
-
|
|
834
|
+
}
|
|
684
835
|
|
|
685
|
-
|
|
836
|
+
continue;
|
|
686
837
|
|
|
687
|
-
|
|
688
|
-
if ( elemNormals[ j ] ) {
|
|
838
|
+
}
|
|
689
839
|
|
|
690
|
-
|
|
840
|
+
const lp = new LineParser( line, lineIndex + 1 );
|
|
841
|
+
lp.seekNonSpace();
|
|
691
842
|
|
|
692
|
-
|
|
843
|
+
if ( lp.isAtTheEnd() ) {
|
|
693
844
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
normals[ index + 1 ] = n.y;
|
|
697
|
-
normals[ index + 2 ] = n.z;
|
|
845
|
+
// Empty line
|
|
846
|
+
continue;
|
|
698
847
|
|
|
699
848
|
}
|
|
700
849
|
|
|
701
|
-
|
|
850
|
+
// Parse the line type
|
|
851
|
+
const lineType = lp.getToken();
|
|
702
852
|
|
|
703
|
-
|
|
853
|
+
let material;
|
|
854
|
+
let colorCode;
|
|
855
|
+
let segment;
|
|
856
|
+
let ccw;
|
|
857
|
+
let doubleSided;
|
|
858
|
+
let v0, v1, v2, v3, c0, c1;
|
|
704
859
|
|
|
705
|
-
|
|
860
|
+
switch ( lineType ) {
|
|
706
861
|
|
|
707
|
-
|
|
862
|
+
// Line type 0: Comment or META
|
|
863
|
+
case '0':
|
|
708
864
|
|
|
709
|
-
|
|
865
|
+
// Parse meta directive
|
|
866
|
+
const meta = lp.getToken();
|
|
710
867
|
|
|
711
|
-
|
|
868
|
+
if ( meta ) {
|
|
712
869
|
|
|
713
|
-
|
|
714
|
-
index0 = offset / 3;
|
|
715
|
-
numGroupVerts = vertices.length;
|
|
870
|
+
switch ( meta ) {
|
|
716
871
|
|
|
717
|
-
|
|
872
|
+
case '!LDRAW_ORG':
|
|
718
873
|
|
|
719
|
-
|
|
874
|
+
type = lp.getToken();
|
|
875
|
+
break;
|
|
720
876
|
|
|
721
|
-
|
|
877
|
+
case '!COLOUR':
|
|
722
878
|
|
|
723
|
-
|
|
879
|
+
material = loader.parseColorMetaDirective( lp );
|
|
880
|
+
if ( material ) {
|
|
724
881
|
|
|
725
|
-
|
|
882
|
+
materials[ material.userData.code ] = material;
|
|
726
883
|
|
|
727
|
-
|
|
884
|
+
} else {
|
|
728
885
|
|
|
729
|
-
|
|
886
|
+
console.warn( 'LDrawLoader: Error parsing material' + lp.getLineNumberString() );
|
|
730
887
|
|
|
731
|
-
|
|
888
|
+
}
|
|
732
889
|
|
|
733
|
-
|
|
890
|
+
break;
|
|
734
891
|
|
|
735
|
-
|
|
892
|
+
case '!CATEGORY':
|
|
736
893
|
|
|
737
|
-
|
|
894
|
+
category = lp.getToken();
|
|
895
|
+
break;
|
|
738
896
|
|
|
739
|
-
|
|
897
|
+
case '!KEYWORDS':
|
|
740
898
|
|
|
741
|
-
|
|
899
|
+
const newKeywords = lp.getRemainingString().split( ',' );
|
|
900
|
+
if ( newKeywords.length > 0 ) {
|
|
742
901
|
|
|
743
|
-
|
|
902
|
+
if ( ! keywords ) {
|
|
744
903
|
|
|
745
|
-
|
|
904
|
+
keywords = [];
|
|
746
905
|
|
|
747
|
-
|
|
906
|
+
}
|
|
748
907
|
|
|
749
|
-
|
|
908
|
+
newKeywords.forEach( function ( keyword ) {
|
|
750
909
|
|
|
751
|
-
|
|
910
|
+
keywords.push( keyword.trim() );
|
|
752
911
|
|
|
753
|
-
|
|
912
|
+
} );
|
|
754
913
|
|
|
755
|
-
|
|
914
|
+
}
|
|
756
915
|
|
|
757
|
-
|
|
758
|
-
const controlArray1 = new Float32Array( elements.length * 3 * 2 );
|
|
759
|
-
const directionArray = new Float32Array( elements.length * 3 * 2 );
|
|
760
|
-
for ( let i = 0, l = elements.length; i < l; i ++ ) {
|
|
916
|
+
break;
|
|
761
917
|
|
|
762
|
-
|
|
763
|
-
const vertices = os.vertices;
|
|
764
|
-
const controlPoints = os.controlPoints;
|
|
765
|
-
const c0 = controlPoints[ 0 ];
|
|
766
|
-
const c1 = controlPoints[ 1 ];
|
|
767
|
-
const v0 = vertices[ 0 ];
|
|
768
|
-
const v1 = vertices[ 1 ];
|
|
769
|
-
const index = i * 3 * 2;
|
|
770
|
-
controlArray0[ index + 0 ] = c0.x;
|
|
771
|
-
controlArray0[ index + 1 ] = c0.y;
|
|
772
|
-
controlArray0[ index + 2 ] = c0.z;
|
|
773
|
-
controlArray0[ index + 3 ] = c0.x;
|
|
774
|
-
controlArray0[ index + 4 ] = c0.y;
|
|
775
|
-
controlArray0[ index + 5 ] = c0.z;
|
|
918
|
+
case 'FILE':
|
|
776
919
|
|
|
777
|
-
|
|
778
|
-
controlArray1[ index + 1 ] = c1.y;
|
|
779
|
-
controlArray1[ index + 2 ] = c1.z;
|
|
780
|
-
controlArray1[ index + 3 ] = c1.x;
|
|
781
|
-
controlArray1[ index + 4 ] = c1.y;
|
|
782
|
-
controlArray1[ index + 5 ] = c1.z;
|
|
920
|
+
if ( lineIndex > 0 ) {
|
|
783
921
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
directionArray[ index + 4 ] = v1.y - v0.y;
|
|
789
|
-
directionArray[ index + 5 ] = v1.z - v0.z;
|
|
922
|
+
// Start embedded text files parsing
|
|
923
|
+
parsingEmbeddedFiles = true;
|
|
924
|
+
currentEmbeddedFileName = lp.getRemainingString();
|
|
925
|
+
currentEmbeddedText = '';
|
|
790
926
|
|
|
791
|
-
|
|
927
|
+
bfcCertified = false;
|
|
928
|
+
bfcCCW = true;
|
|
792
929
|
|
|
793
|
-
|
|
794
|
-
bufferGeometry.setAttribute( 'control1', new BufferAttribute( controlArray1, 3, false ) );
|
|
795
|
-
bufferGeometry.setAttribute( 'direction', new BufferAttribute( directionArray, 3, false ) );
|
|
930
|
+
}
|
|
796
931
|
|
|
797
|
-
|
|
932
|
+
break;
|
|
798
933
|
|
|
799
|
-
|
|
934
|
+
case 'BFC':
|
|
800
935
|
|
|
801
|
-
|
|
936
|
+
// Changes to the backface culling state
|
|
937
|
+
while ( ! lp.isAtTheEnd() ) {
|
|
802
938
|
|
|
803
|
-
|
|
939
|
+
const token = lp.getToken();
|
|
804
940
|
|
|
805
|
-
|
|
941
|
+
switch ( token ) {
|
|
806
942
|
|
|
807
|
-
|
|
943
|
+
case 'CERTIFY':
|
|
944
|
+
case 'NOCERTIFY':
|
|
808
945
|
|
|
809
|
-
|
|
946
|
+
bfcCertified = token === 'CERTIFY';
|
|
947
|
+
bfcCCW = true;
|
|
810
948
|
|
|
811
|
-
|
|
812
|
-
this.materials = [];
|
|
949
|
+
break;
|
|
813
950
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
this.cache = new LDrawFileCache( this );
|
|
951
|
+
case 'CW':
|
|
952
|
+
case 'CCW':
|
|
817
953
|
|
|
818
|
-
|
|
819
|
-
this.fileMap = null;
|
|
954
|
+
bfcCCW = token === 'CCW';
|
|
820
955
|
|
|
821
|
-
|
|
956
|
+
break;
|
|
822
957
|
|
|
823
|
-
|
|
824
|
-
this.setMaterials( [
|
|
825
|
-
this.parseColourMetaDirective( new LineParser( 'Main_Colour CODE 16 VALUE #FF8080 EDGE #333333' ) ),
|
|
826
|
-
this.parseColourMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) )
|
|
827
|
-
] );
|
|
958
|
+
case 'INVERTNEXT':
|
|
828
959
|
|
|
829
|
-
|
|
830
|
-
// If not (the default), only one object which contains all the merged primitives will be created.
|
|
831
|
-
this.separateObjects = false;
|
|
960
|
+
bfcInverted = true;
|
|
832
961
|
|
|
833
|
-
|
|
834
|
-
this.smoothNormals = true;
|
|
962
|
+
break;
|
|
835
963
|
|
|
836
|
-
|
|
837
|
-
|
|
964
|
+
case 'CLIP':
|
|
965
|
+
case 'NOCLIP':
|
|
838
966
|
|
|
839
|
-
|
|
967
|
+
bfcCull = token === 'CLIP';
|
|
840
968
|
|
|
841
|
-
|
|
969
|
+
break;
|
|
842
970
|
|
|
843
|
-
|
|
844
|
-
return this;
|
|
971
|
+
default:
|
|
845
972
|
|
|
846
|
-
|
|
973
|
+
console.warn( 'THREE.LDrawLoader: BFC directive "' + token + '" is unknown.' );
|
|
847
974
|
|
|
848
|
-
|
|
975
|
+
break;
|
|
849
976
|
|
|
850
|
-
|
|
851
|
-
fileLoader.setPath( this.path );
|
|
852
|
-
fileLoader.setRequestHeader( this.requestHeader );
|
|
853
|
-
fileLoader.setWithCredentials( this.withCredentials );
|
|
977
|
+
}
|
|
854
978
|
|
|
855
|
-
|
|
856
|
-
const colorLineRegex = /^0 !COLOUR/;
|
|
857
|
-
const lines = text.split( /[\n\r]/g );
|
|
858
|
-
const materials = [];
|
|
859
|
-
for ( let i = 0, l = lines.length; i < l; i ++ ) {
|
|
979
|
+
}
|
|
860
980
|
|
|
861
|
-
|
|
862
|
-
if ( colorLineRegex.test( line ) ) {
|
|
981
|
+
break;
|
|
863
982
|
|
|
864
|
-
|
|
865
|
-
const material = this.parseColourMetaDirective( new LineParser( directive ) );
|
|
866
|
-
materials.push( material );
|
|
983
|
+
case 'STEP':
|
|
867
984
|
|
|
868
|
-
|
|
985
|
+
startingConstructionStep = true;
|
|
869
986
|
|
|
870
|
-
|
|
987
|
+
break;
|
|
871
988
|
|
|
872
|
-
|
|
989
|
+
default:
|
|
990
|
+
// Other meta directives are not implemented
|
|
991
|
+
break;
|
|
873
992
|
|
|
874
|
-
|
|
993
|
+
}
|
|
875
994
|
|
|
876
|
-
|
|
995
|
+
}
|
|
877
996
|
|
|
878
|
-
|
|
997
|
+
break;
|
|
879
998
|
|
|
880
|
-
|
|
999
|
+
// Line type 1: Sub-object file
|
|
1000
|
+
case '1':
|
|
881
1001
|
|
|
882
|
-
|
|
1002
|
+
colorCode = lp.getToken();
|
|
1003
|
+
material = getLocalMaterial( colorCode );
|
|
883
1004
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
1005
|
+
const posX = parseFloat( lp.getToken() );
|
|
1006
|
+
const posY = parseFloat( lp.getToken() );
|
|
1007
|
+
const posZ = parseFloat( lp.getToken() );
|
|
1008
|
+
const m0 = parseFloat( lp.getToken() );
|
|
1009
|
+
const m1 = parseFloat( lp.getToken() );
|
|
1010
|
+
const m2 = parseFloat( lp.getToken() );
|
|
1011
|
+
const m3 = parseFloat( lp.getToken() );
|
|
1012
|
+
const m4 = parseFloat( lp.getToken() );
|
|
1013
|
+
const m5 = parseFloat( lp.getToken() );
|
|
1014
|
+
const m6 = parseFloat( lp.getToken() );
|
|
1015
|
+
const m7 = parseFloat( lp.getToken() );
|
|
1016
|
+
const m8 = parseFloat( lp.getToken() );
|
|
889
1017
|
|
|
890
|
-
|
|
891
|
-
|
|
1018
|
+
const matrix = new Matrix4().set(
|
|
1019
|
+
m0, m1, m2, posX,
|
|
1020
|
+
m3, m4, m5, posY,
|
|
1021
|
+
m6, m7, m8, posZ,
|
|
1022
|
+
0, 0, 0, 1
|
|
1023
|
+
);
|
|
892
1024
|
|
|
893
|
-
|
|
1025
|
+
let fileName = lp.getRemainingString().trim().replace( /\\/g, '/' );
|
|
894
1026
|
|
|
895
|
-
|
|
1027
|
+
if ( loader.fileMap[ fileName ] ) {
|
|
896
1028
|
|
|
897
|
-
|
|
1029
|
+
// Found the subobject path in the preloaded file path map
|
|
1030
|
+
fileName = loader.fileMap[ fileName ];
|
|
898
1031
|
|
|
899
|
-
|
|
1032
|
+
} else {
|
|
900
1033
|
|
|
901
|
-
|
|
1034
|
+
// Standardized subfolders
|
|
1035
|
+
if ( fileName.startsWith( 's/' ) ) {
|
|
902
1036
|
|
|
903
|
-
|
|
904
|
-
this.processObject( text, null, path, this.rootParseScope )
|
|
905
|
-
.then( function ( result ) {
|
|
1037
|
+
fileName = 'parts/' + fileName;
|
|
906
1038
|
|
|
907
|
-
|
|
1039
|
+
} else if ( fileName.startsWith( '48/' ) ) {
|
|
908
1040
|
|
|
909
|
-
|
|
1041
|
+
fileName = 'p/' + fileName;
|
|
910
1042
|
|
|
911
|
-
|
|
1043
|
+
}
|
|
912
1044
|
|
|
913
|
-
|
|
1045
|
+
}
|
|
914
1046
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
1047
|
+
subobjects.push( {
|
|
1048
|
+
material: material,
|
|
1049
|
+
colorCode: colorCode,
|
|
1050
|
+
matrix: matrix,
|
|
1051
|
+
fileName: fileName,
|
|
1052
|
+
inverted: bfcInverted,
|
|
1053
|
+
startingConstructionStep: startingConstructionStep
|
|
1054
|
+
} );
|
|
918
1055
|
|
|
919
|
-
|
|
1056
|
+
bfcInverted = false;
|
|
920
1057
|
|
|
921
|
-
|
|
1058
|
+
break;
|
|
922
1059
|
|
|
923
|
-
|
|
1060
|
+
// Line type 2: Line segment
|
|
1061
|
+
case '2':
|
|
924
1062
|
|
|
925
|
-
|
|
1063
|
+
colorCode = lp.getToken();
|
|
1064
|
+
material = getLocalMaterial( colorCode );
|
|
1065
|
+
v0 = lp.getVector();
|
|
1066
|
+
v1 = lp.getVector();
|
|
926
1067
|
|
|
927
|
-
|
|
1068
|
+
segment = {
|
|
1069
|
+
material: material,
|
|
1070
|
+
colorCode: colorCode,
|
|
1071
|
+
vertices: [ v0, v1 ],
|
|
1072
|
+
};
|
|
928
1073
|
|
|
929
|
-
|
|
1074
|
+
lineSegments.push( segment );
|
|
930
1075
|
|
|
931
|
-
|
|
1076
|
+
break;
|
|
932
1077
|
|
|
933
|
-
|
|
1078
|
+
// Line type 5: Conditional Line segment
|
|
1079
|
+
case '5':
|
|
934
1080
|
|
|
935
|
-
|
|
1081
|
+
colorCode = lp.getToken();
|
|
1082
|
+
material = getLocalMaterial( colorCode );
|
|
1083
|
+
v0 = lp.getVector();
|
|
1084
|
+
v1 = lp.getVector();
|
|
1085
|
+
c0 = lp.getVector();
|
|
1086
|
+
c1 = lp.getVector();
|
|
936
1087
|
|
|
937
|
-
|
|
1088
|
+
segment = {
|
|
1089
|
+
material: material,
|
|
1090
|
+
colorCode: colorCode,
|
|
1091
|
+
vertices: [ v0, v1 ],
|
|
1092
|
+
controlPoints: [ c0, c1 ],
|
|
1093
|
+
};
|
|
938
1094
|
|
|
939
|
-
|
|
1095
|
+
conditionalSegments.push( segment );
|
|
940
1096
|
|
|
941
|
-
|
|
1097
|
+
break;
|
|
942
1098
|
|
|
943
|
-
|
|
944
|
-
|
|
1099
|
+
// Line type 3: Triangle
|
|
1100
|
+
case '3':
|
|
1101
|
+
|
|
1102
|
+
colorCode = lp.getToken();
|
|
1103
|
+
material = getLocalMaterial( colorCode );
|
|
1104
|
+
ccw = bfcCCW;
|
|
1105
|
+
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1106
|
+
|
|
1107
|
+
if ( ccw === true ) {
|
|
1108
|
+
|
|
1109
|
+
v0 = lp.getVector();
|
|
1110
|
+
v1 = lp.getVector();
|
|
1111
|
+
v2 = lp.getVector();
|
|
1112
|
+
|
|
1113
|
+
} else {
|
|
1114
|
+
|
|
1115
|
+
v2 = lp.getVector();
|
|
1116
|
+
v1 = lp.getVector();
|
|
1117
|
+
v0 = lp.getVector();
|
|
1118
|
+
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
faces.push( {
|
|
1122
|
+
material: material,
|
|
1123
|
+
colorCode: colorCode,
|
|
1124
|
+
faceNormal: null,
|
|
1125
|
+
vertices: [ v0, v1, v2 ],
|
|
1126
|
+
normals: [ null, null, null ],
|
|
1127
|
+
} );
|
|
1128
|
+
totalFaces ++;
|
|
1129
|
+
|
|
1130
|
+
if ( doubleSided === true ) {
|
|
1131
|
+
|
|
1132
|
+
faces.push( {
|
|
1133
|
+
material: material,
|
|
1134
|
+
colorCode: colorCode,
|
|
1135
|
+
faceNormal: null,
|
|
1136
|
+
vertices: [ v2, v1, v0 ],
|
|
1137
|
+
normals: [ null, null, null ],
|
|
1138
|
+
} );
|
|
1139
|
+
totalFaces ++;
|
|
1140
|
+
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
break;
|
|
1144
|
+
|
|
1145
|
+
// Line type 4: Quadrilateral
|
|
1146
|
+
case '4':
|
|
1147
|
+
|
|
1148
|
+
colorCode = lp.getToken();
|
|
1149
|
+
material = getLocalMaterial( colorCode );
|
|
1150
|
+
ccw = bfcCCW;
|
|
1151
|
+
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1152
|
+
|
|
1153
|
+
if ( ccw === true ) {
|
|
1154
|
+
|
|
1155
|
+
v0 = lp.getVector();
|
|
1156
|
+
v1 = lp.getVector();
|
|
1157
|
+
v2 = lp.getVector();
|
|
1158
|
+
v3 = lp.getVector();
|
|
1159
|
+
|
|
1160
|
+
} else {
|
|
1161
|
+
|
|
1162
|
+
v3 = lp.getVector();
|
|
1163
|
+
v2 = lp.getVector();
|
|
1164
|
+
v1 = lp.getVector();
|
|
1165
|
+
v0 = lp.getVector();
|
|
1166
|
+
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// specifically place the triangle diagonal in the v0 and v1 slots so we can
|
|
1170
|
+
// account for the doubling of vertices later when smoothing normals.
|
|
1171
|
+
faces.push( {
|
|
1172
|
+
material: material,
|
|
1173
|
+
colorCode: colorCode,
|
|
1174
|
+
faceNormal: null,
|
|
1175
|
+
vertices: [ v0, v1, v2, v3 ],
|
|
1176
|
+
normals: [ null, null, null, null ],
|
|
1177
|
+
} );
|
|
1178
|
+
totalFaces += 2;
|
|
1179
|
+
|
|
1180
|
+
if ( doubleSided === true ) {
|
|
1181
|
+
|
|
1182
|
+
faces.push( {
|
|
1183
|
+
material: material,
|
|
1184
|
+
colorCode: colorCode,
|
|
1185
|
+
faceNormal: null,
|
|
1186
|
+
vertices: [ v3, v2, v1, v0 ],
|
|
1187
|
+
normals: [ null, null, null, null ],
|
|
1188
|
+
} );
|
|
1189
|
+
totalFaces += 2;
|
|
1190
|
+
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
break;
|
|
1194
|
+
|
|
1195
|
+
default:
|
|
1196
|
+
throw new Error( 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.' );
|
|
945
1197
|
|
|
946
1198
|
}
|
|
947
1199
|
|
|
948
1200
|
}
|
|
949
1201
|
|
|
950
|
-
|
|
1202
|
+
if ( parsingEmbeddedFiles ) {
|
|
951
1203
|
|
|
952
|
-
|
|
953
|
-
lib: matLib,
|
|
954
|
-
url: null,
|
|
1204
|
+
this.setData( currentEmbeddedFileName, currentEmbeddedText );
|
|
955
1205
|
|
|
956
|
-
|
|
957
|
-
subobjects: null,
|
|
958
|
-
numSubobjects: 0,
|
|
959
|
-
subobjectIndex: 0,
|
|
960
|
-
inverted: false,
|
|
961
|
-
category: null,
|
|
962
|
-
keywords: null,
|
|
1206
|
+
}
|
|
963
1207
|
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1208
|
+
return {
|
|
1209
|
+
faces,
|
|
1210
|
+
conditionalSegments,
|
|
1211
|
+
lineSegments,
|
|
1212
|
+
type,
|
|
1213
|
+
category,
|
|
1214
|
+
keywords,
|
|
1215
|
+
subobjects,
|
|
1216
|
+
totalFaces,
|
|
1217
|
+
startingConstructionStep,
|
|
1218
|
+
materials
|
|
1219
|
+
};
|
|
970
1220
|
|
|
971
|
-
|
|
972
|
-
isFromParse: true,
|
|
1221
|
+
}
|
|
973
1222
|
|
|
974
|
-
|
|
975
|
-
lineSegments: null,
|
|
976
|
-
conditionalSegments: null,
|
|
977
|
-
totalFaces: 0,
|
|
1223
|
+
loadData( fileName ) {
|
|
978
1224
|
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
};
|
|
1225
|
+
const key = fileName.toLowerCase();
|
|
1226
|
+
if ( ! ( key in this.cache ) ) {
|
|
982
1227
|
|
|
983
|
-
|
|
1228
|
+
this.cache[ key ] = this.fetchData( fileName ).then( text => {
|
|
1229
|
+
|
|
1230
|
+
return this.parse( text );
|
|
1231
|
+
|
|
1232
|
+
} );
|
|
1233
|
+
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
return this.cache[ key ].then( result => {
|
|
1237
|
+
|
|
1238
|
+
return this.cloneResult( result );
|
|
1239
|
+
|
|
1240
|
+
} );
|
|
984
1241
|
|
|
985
1242
|
}
|
|
986
1243
|
|
|
987
|
-
|
|
1244
|
+
setData( fileName, text ) {
|
|
988
1245
|
|
|
989
|
-
|
|
1246
|
+
const key = fileName.toLowerCase();
|
|
1247
|
+
this.cache[ key ] = Promise.resolve( this.parse( text ) );
|
|
990
1248
|
|
|
991
|
-
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
function sortByMaterial( a, b ) {
|
|
1254
|
+
|
|
1255
|
+
if ( a.colorCode === b.colorCode ) {
|
|
1256
|
+
|
|
1257
|
+
return 0;
|
|
1258
|
+
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
if ( a.colorCode < b.colorCode ) {
|
|
1262
|
+
|
|
1263
|
+
return - 1;
|
|
1264
|
+
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
return 1;
|
|
1268
|
+
|
|
1269
|
+
}
|
|
992
1270
|
|
|
993
|
-
|
|
1271
|
+
function createObject( elements, elementSize, isConditionalSegments = false, totalElements = null ) {
|
|
994
1272
|
|
|
995
|
-
|
|
1273
|
+
// Creates a LineSegments (elementSize = 2) or a Mesh (elementSize = 3 )
|
|
1274
|
+
// With per face / segment material, implemented with mesh groups and materials array
|
|
996
1275
|
|
|
997
|
-
|
|
1276
|
+
// Sort the faces or line segments by color code to make later the mesh groups
|
|
1277
|
+
elements.sort( sortByMaterial );
|
|
998
1278
|
|
|
999
|
-
|
|
1279
|
+
if ( totalElements === null ) {
|
|
1000
1280
|
|
|
1001
|
-
|
|
1281
|
+
totalElements = elements.length;
|
|
1002
1282
|
|
|
1003
1283
|
}
|
|
1004
1284
|
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1285
|
+
const positions = new Float32Array( elementSize * totalElements * 3 );
|
|
1286
|
+
const normals = elementSize === 3 ? new Float32Array( elementSize * totalElements * 3 ) : null;
|
|
1287
|
+
const materials = [];
|
|
1008
1288
|
|
|
1009
|
-
|
|
1289
|
+
const quadArray = new Array( 6 );
|
|
1290
|
+
const bufferGeometry = new BufferGeometry();
|
|
1291
|
+
let prevMaterial = null;
|
|
1292
|
+
let index0 = 0;
|
|
1293
|
+
let numGroupVerts = 0;
|
|
1294
|
+
let offset = 0;
|
|
1010
1295
|
|
|
1011
|
-
|
|
1296
|
+
for ( let iElem = 0, nElem = elements.length; iElem < nElem; iElem ++ ) {
|
|
1012
1297
|
|
|
1013
|
-
|
|
1298
|
+
const elem = elements[ iElem ];
|
|
1299
|
+
let vertices = elem.vertices;
|
|
1300
|
+
if ( vertices.length === 4 ) {
|
|
1014
1301
|
|
|
1015
|
-
|
|
1302
|
+
quadArray[ 0 ] = vertices[ 0 ];
|
|
1303
|
+
quadArray[ 1 ] = vertices[ 1 ];
|
|
1304
|
+
quadArray[ 2 ] = vertices[ 2 ];
|
|
1305
|
+
quadArray[ 3 ] = vertices[ 0 ];
|
|
1306
|
+
quadArray[ 4 ] = vertices[ 2 ];
|
|
1307
|
+
quadArray[ 5 ] = vertices[ 3 ];
|
|
1308
|
+
vertices = quadArray;
|
|
1016
1309
|
|
|
1017
1310
|
}
|
|
1018
1311
|
|
|
1019
|
-
|
|
1312
|
+
for ( let j = 0, l = vertices.length; j < l; j ++ ) {
|
|
1020
1313
|
|
|
1021
|
-
const
|
|
1314
|
+
const v = vertices[ j ];
|
|
1315
|
+
const index = offset + j * 3;
|
|
1316
|
+
positions[ index + 0 ] = v.x;
|
|
1317
|
+
positions[ index + 1 ] = v.y;
|
|
1318
|
+
positions[ index + 2 ] = v.z;
|
|
1022
1319
|
|
|
1023
|
-
|
|
1320
|
+
}
|
|
1024
1321
|
|
|
1025
|
-
|
|
1322
|
+
// create the normals array if this is a set of faces
|
|
1323
|
+
if ( elementSize === 3 ) {
|
|
1026
1324
|
|
|
1027
|
-
|
|
1325
|
+
if ( ! elem.faceNormal ) {
|
|
1028
1326
|
|
|
1029
|
-
|
|
1327
|
+
const v0 = vertices[ 0 ];
|
|
1328
|
+
const v1 = vertices[ 1 ];
|
|
1329
|
+
const v2 = vertices[ 2 ];
|
|
1330
|
+
_tempVec0.subVectors( v1, v0 );
|
|
1331
|
+
_tempVec1.subVectors( v2, v1 );
|
|
1332
|
+
elem.faceNormal = new Vector3()
|
|
1333
|
+
.crossVectors( _tempVec0, _tempVec1 )
|
|
1334
|
+
.normalize();
|
|
1030
1335
|
|
|
1031
1336
|
}
|
|
1032
1337
|
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
// Material was not found
|
|
1036
|
-
return null;
|
|
1037
|
-
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
parseColourMetaDirective( lineParser ) {
|
|
1338
|
+
let elemNormals = elem.normals;
|
|
1339
|
+
if ( elemNormals.length === 4 ) {
|
|
1041
1340
|
|
|
1042
|
-
|
|
1341
|
+
quadArray[ 0 ] = elemNormals[ 0 ];
|
|
1342
|
+
quadArray[ 1 ] = elemNormals[ 1 ];
|
|
1343
|
+
quadArray[ 2 ] = elemNormals[ 2 ];
|
|
1344
|
+
quadArray[ 3 ] = elemNormals[ 0 ];
|
|
1345
|
+
quadArray[ 4 ] = elemNormals[ 2 ];
|
|
1346
|
+
quadArray[ 5 ] = elemNormals[ 3 ];
|
|
1347
|
+
elemNormals = quadArray;
|
|
1043
1348
|
|
|
1044
|
-
|
|
1349
|
+
}
|
|
1045
1350
|
|
|
1046
|
-
|
|
1047
|
-
let colour = 0xFF00FF;
|
|
1048
|
-
let edgeColour = 0xFF00FF;
|
|
1351
|
+
for ( let j = 0, l = elemNormals.length; j < l; j ++ ) {
|
|
1049
1352
|
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
// Self-illumination:
|
|
1054
|
-
let luminance = 0;
|
|
1353
|
+
// use face normal if a vertex normal is not provided
|
|
1354
|
+
let n = elem.faceNormal;
|
|
1355
|
+
if ( elemNormals[ j ] ) {
|
|
1055
1356
|
|
|
1056
|
-
|
|
1357
|
+
n = elemNormals[ j ].norm;
|
|
1057
1358
|
|
|
1058
|
-
|
|
1359
|
+
}
|
|
1059
1360
|
|
|
1060
|
-
|
|
1061
|
-
|
|
1361
|
+
const index = offset + j * 3;
|
|
1362
|
+
normals[ index + 0 ] = n.x;
|
|
1363
|
+
normals[ index + 1 ] = n.y;
|
|
1364
|
+
normals[ index + 2 ] = n.z;
|
|
1062
1365
|
|
|
1063
|
-
|
|
1366
|
+
}
|
|
1064
1367
|
|
|
1065
1368
|
}
|
|
1066
1369
|
|
|
1067
|
-
|
|
1068
|
-
let token = null;
|
|
1069
|
-
while ( true ) {
|
|
1070
|
-
|
|
1071
|
-
token = lineParser.getToken();
|
|
1370
|
+
if ( prevMaterial !== elem.material ) {
|
|
1072
1371
|
|
|
1073
|
-
if (
|
|
1372
|
+
if ( prevMaterial !== null ) {
|
|
1074
1373
|
|
|
1075
|
-
|
|
1374
|
+
bufferGeometry.addGroup( index0, numGroupVerts, materials.length - 1 );
|
|
1076
1375
|
|
|
1077
1376
|
}
|
|
1078
1377
|
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
case 'CODE':
|
|
1378
|
+
const material = elem.material;
|
|
1379
|
+
if ( elementSize === 3 ) {
|
|
1082
1380
|
|
|
1083
|
-
|
|
1084
|
-
break;
|
|
1381
|
+
materials.push( material );
|
|
1085
1382
|
|
|
1086
|
-
|
|
1383
|
+
} else if ( elementSize === 2 ) {
|
|
1087
1384
|
|
|
1088
|
-
|
|
1089
|
-
if ( colour.startsWith( '0x' ) ) {
|
|
1385
|
+
if ( isConditionalSegments ) {
|
|
1090
1386
|
|
|
1091
|
-
|
|
1387
|
+
materials.push( material.userData.edgeMaterial.userData.conditionalEdgeMaterial );
|
|
1092
1388
|
|
|
1093
|
-
|
|
1389
|
+
} else {
|
|
1094
1390
|
|
|
1095
|
-
|
|
1391
|
+
materials.push( material.userData.edgeMaterial );
|
|
1096
1392
|
|
|
1097
|
-
|
|
1393
|
+
}
|
|
1098
1394
|
|
|
1099
|
-
|
|
1395
|
+
}
|
|
1100
1396
|
|
|
1101
|
-
|
|
1397
|
+
prevMaterial = elem.material;
|
|
1398
|
+
index0 = offset / 3;
|
|
1399
|
+
numGroupVerts = vertices.length;
|
|
1102
1400
|
|
|
1103
|
-
|
|
1104
|
-
if ( edgeColour.startsWith( '0x' ) ) {
|
|
1401
|
+
} else {
|
|
1105
1402
|
|
|
1106
|
-
|
|
1403
|
+
numGroupVerts += vertices.length;
|
|
1107
1404
|
|
|
1108
|
-
|
|
1405
|
+
}
|
|
1109
1406
|
|
|
1110
|
-
|
|
1111
|
-
edgeMaterial = this.getMaterial( edgeColour );
|
|
1112
|
-
if ( ! edgeMaterial ) {
|
|
1407
|
+
offset += 3 * vertices.length;
|
|
1113
1408
|
|
|
1114
|
-
|
|
1409
|
+
}
|
|
1115
1410
|
|
|
1116
|
-
|
|
1411
|
+
if ( numGroupVerts > 0 ) {
|
|
1117
1412
|
|
|
1118
|
-
|
|
1119
|
-
edgeMaterial = edgeMaterial.userData.edgeMaterial;
|
|
1413
|
+
bufferGeometry.addGroup( index0, Infinity, materials.length - 1 );
|
|
1120
1414
|
|
|
1121
|
-
|
|
1415
|
+
}
|
|
1122
1416
|
|
|
1123
|
-
|
|
1417
|
+
bufferGeometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
|
|
1124
1418
|
|
|
1125
|
-
|
|
1419
|
+
if ( normals !== null ) {
|
|
1126
1420
|
|
|
1127
|
-
|
|
1421
|
+
bufferGeometry.setAttribute( 'normal', new BufferAttribute( normals, 3 ) );
|
|
1128
1422
|
|
|
1129
|
-
|
|
1423
|
+
}
|
|
1130
1424
|
|
|
1131
|
-
|
|
1425
|
+
let object3d = null;
|
|
1132
1426
|
|
|
1133
|
-
|
|
1427
|
+
if ( elementSize === 2 ) {
|
|
1134
1428
|
|
|
1135
|
-
|
|
1429
|
+
object3d = new LineSegments( bufferGeometry, materials.length === 1 ? materials[ 0 ] : materials );
|
|
1136
1430
|
|
|
1137
|
-
|
|
1431
|
+
} else if ( elementSize === 3 ) {
|
|
1138
1432
|
|
|
1139
|
-
|
|
1433
|
+
object3d = new Mesh( bufferGeometry, materials.length === 1 ? materials[ 0 ] : materials );
|
|
1140
1434
|
|
|
1141
|
-
|
|
1435
|
+
}
|
|
1142
1436
|
|
|
1143
|
-
|
|
1437
|
+
if ( isConditionalSegments ) {
|
|
1144
1438
|
|
|
1145
|
-
|
|
1439
|
+
object3d.isConditionalLine = true;
|
|
1146
1440
|
|
|
1147
|
-
|
|
1441
|
+
const controlArray0 = new Float32Array( elements.length * 3 * 2 );
|
|
1442
|
+
const controlArray1 = new Float32Array( elements.length * 3 * 2 );
|
|
1443
|
+
const directionArray = new Float32Array( elements.length * 3 * 2 );
|
|
1444
|
+
for ( let i = 0, l = elements.length; i < l; i ++ ) {
|
|
1148
1445
|
|
|
1149
|
-
|
|
1446
|
+
const os = elements[ i ];
|
|
1447
|
+
const vertices = os.vertices;
|
|
1448
|
+
const controlPoints = os.controlPoints;
|
|
1449
|
+
const c0 = controlPoints[ 0 ];
|
|
1450
|
+
const c1 = controlPoints[ 1 ];
|
|
1451
|
+
const v0 = vertices[ 0 ];
|
|
1452
|
+
const v1 = vertices[ 1 ];
|
|
1453
|
+
const index = i * 3 * 2;
|
|
1454
|
+
controlArray0[ index + 0 ] = c0.x;
|
|
1455
|
+
controlArray0[ index + 1 ] = c0.y;
|
|
1456
|
+
controlArray0[ index + 2 ] = c0.z;
|
|
1457
|
+
controlArray0[ index + 3 ] = c0.x;
|
|
1458
|
+
controlArray0[ index + 4 ] = c0.y;
|
|
1459
|
+
controlArray0[ index + 5 ] = c0.z;
|
|
1150
1460
|
|
|
1151
|
-
|
|
1461
|
+
controlArray1[ index + 0 ] = c1.x;
|
|
1462
|
+
controlArray1[ index + 1 ] = c1.y;
|
|
1463
|
+
controlArray1[ index + 2 ] = c1.z;
|
|
1464
|
+
controlArray1[ index + 3 ] = c1.x;
|
|
1465
|
+
controlArray1[ index + 4 ] = c1.y;
|
|
1466
|
+
controlArray1[ index + 5 ] = c1.z;
|
|
1152
1467
|
|
|
1153
|
-
|
|
1468
|
+
directionArray[ index + 0 ] = v1.x - v0.x;
|
|
1469
|
+
directionArray[ index + 1 ] = v1.y - v0.y;
|
|
1470
|
+
directionArray[ index + 2 ] = v1.z - v0.z;
|
|
1471
|
+
directionArray[ index + 3 ] = v1.x - v0.x;
|
|
1472
|
+
directionArray[ index + 4 ] = v1.y - v0.y;
|
|
1473
|
+
directionArray[ index + 5 ] = v1.z - v0.z;
|
|
1154
1474
|
|
|
1155
|
-
|
|
1475
|
+
}
|
|
1156
1476
|
|
|
1157
|
-
|
|
1477
|
+
bufferGeometry.setAttribute( 'control0', new BufferAttribute( controlArray0, 3, false ) );
|
|
1478
|
+
bufferGeometry.setAttribute( 'control1', new BufferAttribute( controlArray1, 3, false ) );
|
|
1479
|
+
bufferGeometry.setAttribute( 'direction', new BufferAttribute( directionArray, 3, false ) );
|
|
1158
1480
|
|
|
1159
|
-
|
|
1160
|
-
finishType = FINISH_TYPE_CHROME;
|
|
1161
|
-
break;
|
|
1481
|
+
}
|
|
1162
1482
|
|
|
1163
|
-
|
|
1164
|
-
finishType = FINISH_TYPE_PEARLESCENT;
|
|
1165
|
-
break;
|
|
1483
|
+
return object3d;
|
|
1166
1484
|
|
|
1167
|
-
|
|
1168
|
-
finishType = FINISH_TYPE_RUBBER;
|
|
1169
|
-
break;
|
|
1485
|
+
}
|
|
1170
1486
|
|
|
1171
|
-
|
|
1172
|
-
finishType = FINISH_TYPE_MATTE_METALLIC;
|
|
1173
|
-
break;
|
|
1487
|
+
//
|
|
1174
1488
|
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
break;
|
|
1489
|
+
const MAIN_COLOUR_CODE = '16';
|
|
1490
|
+
const MAIN_EDGE_COLOUR_CODE = '24';
|
|
1178
1491
|
|
|
1179
|
-
|
|
1180
|
-
// Not implemented
|
|
1181
|
-
lineParser.setToEnd();
|
|
1182
|
-
break;
|
|
1492
|
+
class LDrawLoader extends Loader {
|
|
1183
1493
|
|
|
1184
|
-
|
|
1185
|
-
throw 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.';
|
|
1186
|
-
break;
|
|
1494
|
+
constructor( manager ) {
|
|
1187
1495
|
|
|
1188
|
-
|
|
1496
|
+
super( manager );
|
|
1189
1497
|
|
|
1190
|
-
|
|
1498
|
+
// Array of THREE.Material
|
|
1499
|
+
this.materials = [];
|
|
1191
1500
|
|
|
1192
|
-
|
|
1501
|
+
// Not using THREE.Cache here because it returns the previous HTML error response instead of calling onError()
|
|
1502
|
+
// This also allows to handle the embedded text files ("0 FILE" lines)
|
|
1503
|
+
this.parseCache = new LDrawParsedCache( this );
|
|
1193
1504
|
|
|
1194
|
-
|
|
1505
|
+
// 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.
|
|
1506
|
+
this.fileMap = {};
|
|
1195
1507
|
|
|
1196
|
-
|
|
1508
|
+
this.rootParseScope = this.newParseScopeLevel();
|
|
1197
1509
|
|
|
1198
|
-
|
|
1199
|
-
|
|
1510
|
+
// Add default main triangle and line edge materials (used in pieces that can be colored with a main color)
|
|
1511
|
+
this.setMaterials( [
|
|
1512
|
+
this.parseColorMetaDirective( new LineParser( 'Main_Colour CODE 16 VALUE #FF8080 EDGE #333333' ) ),
|
|
1513
|
+
this.parseColorMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) )
|
|
1514
|
+
] );
|
|
1200
1515
|
|
|
1201
|
-
|
|
1516
|
+
// If this flag is set to true the vertex normals will be smoothed.
|
|
1517
|
+
this.smoothNormals = true;
|
|
1202
1518
|
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
const hsl = specular.getHSL( { h: 0, s: 0, l: 0 } );
|
|
1206
|
-
hsl.h = ( hsl.h + 0.5 ) % 1;
|
|
1207
|
-
hsl.l = Math.min( 1, hsl.l + ( 1 - hsl.l ) * 0.7 );
|
|
1208
|
-
specular.setHSL( hsl.h, hsl.s, hsl.l );
|
|
1519
|
+
// The path to load parts from the LDraw parts library from.
|
|
1520
|
+
this.partsLibraryPath = '';
|
|
1209
1521
|
|
|
1210
|
-
|
|
1211
|
-
break;
|
|
1522
|
+
}
|
|
1212
1523
|
|
|
1213
|
-
|
|
1524
|
+
setPartsLibraryPath( path ) {
|
|
1214
1525
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
break;
|
|
1526
|
+
this.partsLibraryPath = path;
|
|
1527
|
+
return this;
|
|
1218
1528
|
|
|
1219
|
-
|
|
1529
|
+
}
|
|
1220
1530
|
|
|
1221
|
-
|
|
1222
|
-
material = new MeshStandardMaterial( { color: colour, roughness: 0.9, metalness: 0 } );
|
|
1223
|
-
break;
|
|
1531
|
+
async preloadMaterials( url ) {
|
|
1224
1532
|
|
|
1225
|
-
|
|
1533
|
+
const fileLoader = new FileLoader( this.manager );
|
|
1534
|
+
fileLoader.setPath( this.path );
|
|
1535
|
+
fileLoader.setRequestHeader( this.requestHeader );
|
|
1536
|
+
fileLoader.setWithCredentials( this.withCredentials );
|
|
1226
1537
|
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1538
|
+
const text = await fileLoader.loadAsync( url );
|
|
1539
|
+
const colorLineRegex = /^0 !COLOUR/;
|
|
1540
|
+
const lines = text.split( /[\n\r]/g );
|
|
1541
|
+
const materials = [];
|
|
1542
|
+
for ( let i = 0, l = lines.length; i < l; i ++ ) {
|
|
1230
1543
|
|
|
1231
|
-
|
|
1544
|
+
const line = lines[ i ];
|
|
1545
|
+
if ( colorLineRegex.test( line ) ) {
|
|
1232
1546
|
|
|
1233
|
-
|
|
1234
|
-
material = new
|
|
1235
|
-
|
|
1547
|
+
const directive = line.replace( colorLineRegex, '' );
|
|
1548
|
+
const material = this.parseColorMetaDirective( new LineParser( directive ) );
|
|
1549
|
+
materials.push( material );
|
|
1236
1550
|
|
|
1237
|
-
|
|
1238
|
-
// Should not happen
|
|
1239
|
-
break;
|
|
1551
|
+
}
|
|
1240
1552
|
|
|
1241
1553
|
}
|
|
1242
1554
|
|
|
1243
|
-
|
|
1244
|
-
material.premultipliedAlpha = true;
|
|
1245
|
-
material.opacity = alpha;
|
|
1246
|
-
material.depthWrite = ! isTransparent;
|
|
1247
|
-
|
|
1248
|
-
material.polygonOffset = true;
|
|
1249
|
-
material.polygonOffsetFactor = 1;
|
|
1555
|
+
this.setMaterials( materials );
|
|
1250
1556
|
|
|
1251
|
-
|
|
1557
|
+
}
|
|
1252
1558
|
|
|
1253
|
-
|
|
1559
|
+
load( url, onLoad, onProgress, onError ) {
|
|
1254
1560
|
|
|
1255
|
-
|
|
1561
|
+
const fileLoader = new FileLoader( this.manager );
|
|
1562
|
+
fileLoader.setPath( this.path );
|
|
1563
|
+
fileLoader.setRequestHeader( this.requestHeader );
|
|
1564
|
+
fileLoader.setWithCredentials( this.withCredentials );
|
|
1565
|
+
fileLoader.load( url, text => {
|
|
1256
1566
|
|
|
1257
|
-
|
|
1567
|
+
const parsedInfo = this.parseCache.parse( text );
|
|
1568
|
+
this.processObject( parsedInfo, null, url, this.rootParseScope )
|
|
1569
|
+
.then( function ( result ) {
|
|
1258
1570
|
|
|
1259
|
-
|
|
1260
|
-
edgeMaterial = new LineBasicMaterial( {
|
|
1261
|
-
color: edgeColour,
|
|
1262
|
-
transparent: isTransparent,
|
|
1263
|
-
opacity: alpha,
|
|
1264
|
-
depthWrite: ! isTransparent
|
|
1265
|
-
} );
|
|
1266
|
-
edgeMaterial.userData.code = code;
|
|
1267
|
-
edgeMaterial.name = name + ' - Edge';
|
|
1571
|
+
onLoad( result.groupObject );
|
|
1268
1572
|
|
|
1269
|
-
|
|
1270
|
-
edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial( {
|
|
1573
|
+
} );
|
|
1271
1574
|
|
|
1272
|
-
|
|
1273
|
-
transparent: isTransparent,
|
|
1274
|
-
depthWrite: ! isTransparent,
|
|
1275
|
-
color: edgeColour,
|
|
1276
|
-
opacity: alpha,
|
|
1575
|
+
}, onProgress, onError );
|
|
1277
1576
|
|
|
1278
|
-
|
|
1577
|
+
}
|
|
1279
1578
|
|
|
1280
|
-
|
|
1579
|
+
parse( text, path, onLoad ) {
|
|
1281
1580
|
|
|
1282
|
-
|
|
1283
|
-
|
|
1581
|
+
// Async parse. This function calls onParse with the parsed THREE.Object3D as parameter
|
|
1582
|
+
const parsedInfo = this.parseCache.parse( text );
|
|
1583
|
+
this.processObject( parsedInfo, null, path, this.rootParseScope )
|
|
1584
|
+
.then( function ( result ) {
|
|
1284
1585
|
|
|
1285
|
-
|
|
1586
|
+
onLoad( result.groupObject );
|
|
1286
1587
|
|
|
1287
|
-
|
|
1588
|
+
} );
|
|
1288
1589
|
|
|
1289
1590
|
}
|
|
1290
1591
|
|
|
1291
|
-
|
|
1592
|
+
setMaterials( materials ) {
|
|
1292
1593
|
|
|
1293
|
-
|
|
1594
|
+
// Clears parse scopes stack, adds new scope with material library
|
|
1595
|
+
this.rootParseScope = this.newParseScopeLevel( materials );
|
|
1596
|
+
this.rootParseScope.isFromParse = false;
|
|
1294
1597
|
|
|
1295
|
-
|
|
1296
|
-
const currentParseScope = parseScope;
|
|
1297
|
-
const parentParseScope = currentParseScope.parentScope;
|
|
1598
|
+
this.materials = materials;
|
|
1298
1599
|
|
|
1299
|
-
|
|
1300
|
-
const mainColourCode = currentParseScope.mainColourCode;
|
|
1301
|
-
const mainEdgeColourCode = currentParseScope.mainEdgeColourCode;
|
|
1600
|
+
return this;
|
|
1302
1601
|
|
|
1602
|
+
}
|
|
1303
1603
|
|
|
1304
|
-
|
|
1305
|
-
let faces;
|
|
1306
|
-
let lineSegments;
|
|
1307
|
-
let conditionalSegments;
|
|
1604
|
+
setFileMap( fileMap ) {
|
|
1308
1605
|
|
|
1309
|
-
|
|
1606
|
+
this.fileMap = fileMap;
|
|
1310
1607
|
|
|
1311
|
-
|
|
1312
|
-
let keywords = null;
|
|
1608
|
+
return this;
|
|
1313
1609
|
|
|
1314
|
-
|
|
1610
|
+
}
|
|
1315
1611
|
|
|
1316
|
-
|
|
1317
|
-
text = text.replace( /\r\n/g, '\n' );
|
|
1612
|
+
newParseScopeLevel( materials = null, parentScope = null ) {
|
|
1318
1613
|
|
|
1319
|
-
|
|
1614
|
+
// Adds a new scope level, assign materials to it and returns it
|
|
1320
1615
|
|
|
1321
|
-
const
|
|
1322
|
-
const numLines = lines.length;
|
|
1616
|
+
const matLib = {};
|
|
1323
1617
|
|
|
1324
|
-
|
|
1325
|
-
let currentEmbeddedFileName = null;
|
|
1326
|
-
let currentEmbeddedText = null;
|
|
1618
|
+
if ( materials ) {
|
|
1327
1619
|
|
|
1328
|
-
|
|
1329
|
-
let bfcCCW = true;
|
|
1330
|
-
let bfcInverted = false;
|
|
1331
|
-
let bfcCull = true;
|
|
1332
|
-
let type = '';
|
|
1620
|
+
for ( let i = 0, n = materials.length; i < n; i ++ ) {
|
|
1333
1621
|
|
|
1334
|
-
|
|
1622
|
+
const material = materials[ i ];
|
|
1623
|
+
matLib[ material.userData.code ] = material;
|
|
1335
1624
|
|
|
1336
|
-
|
|
1337
|
-
function parseColourCode( lineParser, forEdge ) {
|
|
1625
|
+
}
|
|
1338
1626
|
|
|
1339
|
-
|
|
1627
|
+
}
|
|
1340
1628
|
|
|
1341
|
-
|
|
1629
|
+
const newParseScope = {
|
|
1342
1630
|
|
|
1343
|
-
|
|
1631
|
+
parentScope: parentScope,
|
|
1632
|
+
lib: matLib,
|
|
1633
|
+
url: null,
|
|
1344
1634
|
|
|
1345
|
-
|
|
1635
|
+
// Subobjects
|
|
1636
|
+
subobjects: null,
|
|
1637
|
+
inverted: false,
|
|
1638
|
+
category: null,
|
|
1639
|
+
keywords: null,
|
|
1346
1640
|
|
|
1347
|
-
|
|
1641
|
+
// Current subobject
|
|
1642
|
+
currentFileName: null,
|
|
1643
|
+
mainColorCode: parentScope ? parentScope.mainColorCode : MAIN_COLOUR_CODE,
|
|
1644
|
+
mainEdgeColorCode: parentScope ? parentScope.mainEdgeColorCode : MAIN_EDGE_COLOUR_CODE,
|
|
1645
|
+
matrix: new Matrix4(),
|
|
1646
|
+
type: 'Model',
|
|
1647
|
+
groupObject: null,
|
|
1348
1648
|
|
|
1349
|
-
|
|
1649
|
+
// If false, it is a root material scope previous to parse
|
|
1650
|
+
isFromParse: true,
|
|
1350
1651
|
|
|
1351
|
-
|
|
1652
|
+
faces: [],
|
|
1653
|
+
lineSegments: [],
|
|
1654
|
+
conditionalSegments: [],
|
|
1655
|
+
totalFaces: 0,
|
|
1656
|
+
faceMaterials: new Set(),
|
|
1352
1657
|
|
|
1353
|
-
|
|
1658
|
+
// If true, this object is the start of a construction step
|
|
1659
|
+
startingConstructionStep: false
|
|
1660
|
+
};
|
|
1354
1661
|
|
|
1355
|
-
|
|
1662
|
+
return newParseScope;
|
|
1356
1663
|
|
|
1357
|
-
|
|
1664
|
+
}
|
|
1358
1665
|
|
|
1359
|
-
|
|
1666
|
+
addMaterial( material, parseScope ) {
|
|
1360
1667
|
|
|
1361
|
-
|
|
1668
|
+
// Adds a material to the material library which is on top of the parse scopes stack. And also to the materials array
|
|
1362
1669
|
|
|
1363
|
-
|
|
1670
|
+
const matLib = parseScope.lib;
|
|
1364
1671
|
|
|
1365
|
-
|
|
1672
|
+
if ( ! matLib[ material.userData.code ] ) {
|
|
1366
1673
|
|
|
1367
|
-
|
|
1674
|
+
this.materials.push( material );
|
|
1368
1675
|
|
|
1369
|
-
|
|
1676
|
+
}
|
|
1370
1677
|
|
|
1371
|
-
|
|
1678
|
+
matLib[ material.userData.code ] = material;
|
|
1372
1679
|
|
|
1373
|
-
|
|
1680
|
+
return this;
|
|
1374
1681
|
|
|
1375
|
-
|
|
1682
|
+
}
|
|
1376
1683
|
|
|
1377
|
-
|
|
1684
|
+
getMaterial( colorCode, parseScope = this.rootParseScope ) {
|
|
1378
1685
|
|
|
1379
|
-
|
|
1686
|
+
// Given a color code search its material in the parse scopes stack
|
|
1380
1687
|
|
|
1381
|
-
|
|
1382
|
-
for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) {
|
|
1688
|
+
if ( colorCode.startsWith( '0x2' ) ) {
|
|
1383
1689
|
|
|
1384
|
-
|
|
1690
|
+
// Special 'direct' material value (RGB color)
|
|
1385
1691
|
|
|
1386
|
-
|
|
1692
|
+
const color = colorCode.substring( 3 );
|
|
1387
1693
|
|
|
1388
|
-
|
|
1694
|
+
return this.parseColorMetaDirective( new LineParser( 'Direct_Color_' + color + ' CODE -1 VALUE #' + color + ' EDGE #' + color + '' ) );
|
|
1389
1695
|
|
|
1390
|
-
|
|
1696
|
+
}
|
|
1391
1697
|
|
|
1392
|
-
|
|
1393
|
-
this.cache.setData( currentEmbeddedFileName.toLowerCase(), currentEmbeddedText );
|
|
1698
|
+
while ( parseScope ) {
|
|
1394
1699
|
|
|
1395
|
-
|
|
1396
|
-
currentEmbeddedFileName = line.substring( 7 );
|
|
1397
|
-
currentEmbeddedText = '';
|
|
1700
|
+
const material = parseScope.lib[ colorCode ];
|
|
1398
1701
|
|
|
1399
|
-
|
|
1702
|
+
if ( material ) {
|
|
1400
1703
|
|
|
1401
|
-
|
|
1704
|
+
return material;
|
|
1402
1705
|
|
|
1403
|
-
|
|
1706
|
+
} else {
|
|
1404
1707
|
|
|
1405
|
-
|
|
1708
|
+
parseScope = parseScope.parentScope;
|
|
1406
1709
|
|
|
1407
1710
|
}
|
|
1408
1711
|
|
|
1409
|
-
|
|
1712
|
+
}
|
|
1410
1713
|
|
|
1411
|
-
|
|
1714
|
+
// Material was not found
|
|
1715
|
+
return null;
|
|
1412
1716
|
|
|
1413
|
-
|
|
1717
|
+
}
|
|
1414
1718
|
|
|
1415
|
-
|
|
1416
|
-
continue;
|
|
1719
|
+
getMainMaterial() {
|
|
1417
1720
|
|
|
1418
|
-
|
|
1721
|
+
return this.getMaterial( MAIN_COLOUR_CODE );
|
|
1722
|
+
}
|
|
1419
1723
|
|
|
1420
|
-
|
|
1421
|
-
const lineType = lp.getToken();
|
|
1724
|
+
getMainEdgeMaterial() {
|
|
1422
1725
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
let inverted;
|
|
1426
|
-
let ccw;
|
|
1427
|
-
let doubleSided;
|
|
1428
|
-
let v0, v1, v2, v3, c0, c1, faceNormal;
|
|
1726
|
+
return this.getMaterial( MAIN_EDGE_COLOUR_CODE );;
|
|
1727
|
+
}
|
|
1429
1728
|
|
|
1430
|
-
|
|
1729
|
+
parseColorMetaDirective( lineParser ) {
|
|
1431
1730
|
|
|
1432
|
-
|
|
1433
|
-
case '0':
|
|
1731
|
+
// Parses a color definition and returns a THREE.Material
|
|
1434
1732
|
|
|
1435
|
-
|
|
1436
|
-
const meta = lp.getToken();
|
|
1733
|
+
let code = null;
|
|
1437
1734
|
|
|
1438
|
-
|
|
1735
|
+
// Triangle and line colors
|
|
1736
|
+
let color = 0xFF00FF;
|
|
1737
|
+
let edgeColor = 0xFF00FF;
|
|
1439
1738
|
|
|
1440
|
-
|
|
1739
|
+
// Transparency
|
|
1740
|
+
let alpha = 1;
|
|
1741
|
+
let isTransparent = false;
|
|
1742
|
+
// Self-illumination:
|
|
1743
|
+
let luminance = 0;
|
|
1441
1744
|
|
|
1442
|
-
|
|
1745
|
+
let finishType = FINISH_TYPE_DEFAULT;
|
|
1443
1746
|
|
|
1444
|
-
|
|
1747
|
+
let edgeMaterial = null;
|
|
1445
1748
|
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
currentParseScope.conditionalSegments = [];
|
|
1449
|
-
currentParseScope.type = type;
|
|
1749
|
+
const name = lineParser.getToken();
|
|
1750
|
+
if ( ! name ) {
|
|
1450
1751
|
|
|
1451
|
-
|
|
1452
|
-
if ( isRoot || scope.separateObjects && ! isPrimitiveType( type ) ) {
|
|
1752
|
+
throw new Error( 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.' );
|
|
1453
1753
|
|
|
1454
|
-
|
|
1754
|
+
}
|
|
1455
1755
|
|
|
1456
|
-
|
|
1756
|
+
// Parse tag tokens and their parameters
|
|
1757
|
+
let token = null;
|
|
1758
|
+
while ( true ) {
|
|
1457
1759
|
|
|
1458
|
-
|
|
1760
|
+
token = lineParser.getToken();
|
|
1459
1761
|
|
|
1460
|
-
|
|
1461
|
-
// needs to be flipped.
|
|
1462
|
-
if (
|
|
1463
|
-
currentParseScope.matrix.determinant() < 0 && (
|
|
1464
|
-
scope.separateObjects && isPrimitiveType( type ) ||
|
|
1465
|
-
! scope.separateObjects
|
|
1466
|
-
) ) {
|
|
1762
|
+
if ( ! token ) {
|
|
1467
1763
|
|
|
1468
|
-
|
|
1764
|
+
break;
|
|
1469
1765
|
|
|
1470
|
-
|
|
1766
|
+
}
|
|
1471
1767
|
|
|
1472
|
-
|
|
1473
|
-
lineSegments = currentParseScope.lineSegments;
|
|
1474
|
-
conditionalSegments = currentParseScope.conditionalSegments;
|
|
1768
|
+
switch ( token.toUpperCase() ) {
|
|
1475
1769
|
|
|
1476
|
-
|
|
1770
|
+
case 'CODE':
|
|
1477
1771
|
|
|
1478
|
-
|
|
1772
|
+
code = lineParser.getToken();
|
|
1773
|
+
break;
|
|
1479
1774
|
|
|
1480
|
-
|
|
1481
|
-
if ( material ) {
|
|
1775
|
+
case 'VALUE':
|
|
1482
1776
|
|
|
1483
|
-
|
|
1777
|
+
color = lineParser.getToken();
|
|
1778
|
+
if ( color.startsWith( '0x' ) ) {
|
|
1484
1779
|
|
|
1485
|
-
|
|
1780
|
+
color = '#' + color.substring( 2 );
|
|
1486
1781
|
|
|
1487
|
-
|
|
1782
|
+
} else if ( ! color.startsWith( '#' ) ) {
|
|
1488
1783
|
|
|
1489
|
-
|
|
1784
|
+
throw new Error( 'LDrawLoader: Invalid color while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
1490
1785
|
|
|
1491
|
-
|
|
1786
|
+
}
|
|
1492
1787
|
|
|
1493
|
-
|
|
1788
|
+
break;
|
|
1494
1789
|
|
|
1495
|
-
|
|
1496
|
-
break;
|
|
1790
|
+
case 'EDGE':
|
|
1497
1791
|
|
|
1498
|
-
|
|
1792
|
+
edgeColor = lineParser.getToken();
|
|
1793
|
+
if ( edgeColor.startsWith( '0x' ) ) {
|
|
1499
1794
|
|
|
1500
|
-
|
|
1501
|
-
if ( newKeywords.length > 0 ) {
|
|
1795
|
+
edgeColor = '#' + edgeColor.substring( 2 );
|
|
1502
1796
|
|
|
1503
|
-
|
|
1797
|
+
} else if ( ! edgeColor.startsWith( '#' ) ) {
|
|
1504
1798
|
|
|
1505
|
-
|
|
1799
|
+
// Try to see if edge color is a color code
|
|
1800
|
+
edgeMaterial = this.getMaterial( edgeColor );
|
|
1801
|
+
if ( ! edgeMaterial ) {
|
|
1506
1802
|
|
|
1507
|
-
|
|
1803
|
+
throw new Error( 'LDrawLoader: Invalid edge color while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
1508
1804
|
|
|
1509
|
-
|
|
1805
|
+
}
|
|
1510
1806
|
|
|
1511
|
-
|
|
1807
|
+
// Get the edge material for this triangle material
|
|
1808
|
+
edgeMaterial = edgeMaterial.userData.edgeMaterial;
|
|
1512
1809
|
|
|
1513
|
-
|
|
1810
|
+
}
|
|
1514
1811
|
|
|
1515
|
-
|
|
1812
|
+
break;
|
|
1516
1813
|
|
|
1517
|
-
|
|
1814
|
+
case 'ALPHA':
|
|
1518
1815
|
|
|
1519
|
-
|
|
1816
|
+
alpha = parseInt( lineParser.getToken() );
|
|
1520
1817
|
|
|
1521
|
-
|
|
1818
|
+
if ( isNaN( alpha ) ) {
|
|
1522
1819
|
|
|
1523
|
-
|
|
1524
|
-
parsingEmbeddedFiles = true;
|
|
1525
|
-
currentEmbeddedFileName = lp.getRemainingString();
|
|
1526
|
-
currentEmbeddedText = '';
|
|
1820
|
+
throw new Error( 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.' );
|
|
1527
1821
|
|
|
1528
|
-
|
|
1529
|
-
bfcCCW = true;
|
|
1822
|
+
}
|
|
1530
1823
|
|
|
1531
|
-
|
|
1824
|
+
alpha = Math.max( 0, Math.min( 1, alpha / 255 ) );
|
|
1532
1825
|
|
|
1533
|
-
|
|
1826
|
+
if ( alpha < 1 ) {
|
|
1827
|
+
|
|
1828
|
+
isTransparent = true;
|
|
1534
1829
|
|
|
1535
|
-
|
|
1830
|
+
}
|
|
1536
1831
|
|
|
1537
|
-
|
|
1538
|
-
while ( ! lp.isAtTheEnd() ) {
|
|
1832
|
+
break;
|
|
1539
1833
|
|
|
1540
|
-
|
|
1834
|
+
case 'LUMINANCE':
|
|
1541
1835
|
|
|
1542
|
-
|
|
1836
|
+
luminance = parseInt( lineParser.getToken() );
|
|
1543
1837
|
|
|
1544
|
-
|
|
1545
|
-
case 'NOCERTIFY':
|
|
1838
|
+
if ( isNaN( luminance ) ) {
|
|
1546
1839
|
|
|
1547
|
-
|
|
1548
|
-
bfcCCW = true;
|
|
1840
|
+
throw new Error( 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.' );
|
|
1549
1841
|
|
|
1550
|
-
|
|
1842
|
+
}
|
|
1551
1843
|
|
|
1552
|
-
|
|
1553
|
-
case 'CCW':
|
|
1844
|
+
luminance = Math.max( 0, Math.min( 1, luminance / 255 ) );
|
|
1554
1845
|
|
|
1555
|
-
|
|
1846
|
+
break;
|
|
1556
1847
|
|
|
1557
|
-
|
|
1848
|
+
case 'CHROME':
|
|
1849
|
+
finishType = FINISH_TYPE_CHROME;
|
|
1850
|
+
break;
|
|
1558
1851
|
|
|
1559
|
-
|
|
1852
|
+
case 'PEARLESCENT':
|
|
1853
|
+
finishType = FINISH_TYPE_PEARLESCENT;
|
|
1854
|
+
break;
|
|
1560
1855
|
|
|
1561
|
-
|
|
1856
|
+
case 'RUBBER':
|
|
1857
|
+
finishType = FINISH_TYPE_RUBBER;
|
|
1858
|
+
break;
|
|
1562
1859
|
|
|
1563
|
-
|
|
1860
|
+
case 'MATTE_METALLIC':
|
|
1861
|
+
finishType = FINISH_TYPE_MATTE_METALLIC;
|
|
1862
|
+
break;
|
|
1564
1863
|
|
|
1565
|
-
|
|
1566
|
-
|
|
1864
|
+
case 'METAL':
|
|
1865
|
+
finishType = FINISH_TYPE_METAL;
|
|
1866
|
+
break;
|
|
1567
1867
|
|
|
1568
|
-
|
|
1868
|
+
case 'MATERIAL':
|
|
1869
|
+
// Not implemented
|
|
1870
|
+
lineParser.setToEnd();
|
|
1871
|
+
break;
|
|
1569
1872
|
|
|
1570
|
-
|
|
1873
|
+
default:
|
|
1874
|
+
throw new Error( 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
1571
1875
|
|
|
1572
|
-
|
|
1876
|
+
}
|
|
1573
1877
|
|
|
1574
|
-
|
|
1878
|
+
}
|
|
1575
1879
|
|
|
1576
|
-
|
|
1880
|
+
let material = null;
|
|
1577
1881
|
|
|
1578
|
-
|
|
1882
|
+
switch ( finishType ) {
|
|
1579
1883
|
|
|
1580
|
-
|
|
1884
|
+
case FINISH_TYPE_DEFAULT:
|
|
1581
1885
|
|
|
1582
|
-
|
|
1886
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0.3, metalness: 0 } );
|
|
1887
|
+
break;
|
|
1583
1888
|
|
|
1584
|
-
|
|
1889
|
+
case FINISH_TYPE_PEARLESCENT:
|
|
1585
1890
|
|
|
1586
|
-
|
|
1891
|
+
// Try to imitate pearlescency by making the surface glossy
|
|
1892
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0.3, metalness: 0.25 } );
|
|
1893
|
+
break;
|
|
1587
1894
|
|
|
1588
|
-
|
|
1895
|
+
case FINISH_TYPE_CHROME:
|
|
1589
1896
|
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1897
|
+
// Mirror finish surface
|
|
1898
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0, metalness: 1 } );
|
|
1899
|
+
break;
|
|
1593
1900
|
|
|
1594
|
-
|
|
1901
|
+
case FINISH_TYPE_RUBBER:
|
|
1595
1902
|
|
|
1596
|
-
|
|
1903
|
+
// Rubber finish
|
|
1904
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0.9, metalness: 0 } );
|
|
1905
|
+
break;
|
|
1597
1906
|
|
|
1598
|
-
|
|
1907
|
+
case FINISH_TYPE_MATTE_METALLIC:
|
|
1599
1908
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1909
|
+
// Brushed metal finish
|
|
1910
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0.8, metalness: 0.4 } );
|
|
1911
|
+
break;
|
|
1602
1912
|
|
|
1603
|
-
|
|
1913
|
+
case FINISH_TYPE_METAL:
|
|
1604
1914
|
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
const m0 = parseFloat( lp.getToken() );
|
|
1609
|
-
const m1 = parseFloat( lp.getToken() );
|
|
1610
|
-
const m2 = parseFloat( lp.getToken() );
|
|
1611
|
-
const m3 = parseFloat( lp.getToken() );
|
|
1612
|
-
const m4 = parseFloat( lp.getToken() );
|
|
1613
|
-
const m5 = parseFloat( lp.getToken() );
|
|
1614
|
-
const m6 = parseFloat( lp.getToken() );
|
|
1615
|
-
const m7 = parseFloat( lp.getToken() );
|
|
1616
|
-
const m8 = parseFloat( lp.getToken() );
|
|
1915
|
+
// Average metal finish
|
|
1916
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0.2, metalness: 0.85 } );
|
|
1917
|
+
break;
|
|
1617
1918
|
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
m6, m7, m8, posZ,
|
|
1622
|
-
0, 0, 0, 1
|
|
1623
|
-
);
|
|
1919
|
+
default:
|
|
1920
|
+
// Should not happen
|
|
1921
|
+
break;
|
|
1624
1922
|
|
|
1625
|
-
|
|
1923
|
+
}
|
|
1626
1924
|
|
|
1627
|
-
|
|
1925
|
+
material.transparent = isTransparent;
|
|
1926
|
+
material.premultipliedAlpha = true;
|
|
1927
|
+
material.opacity = alpha;
|
|
1928
|
+
material.depthWrite = ! isTransparent;
|
|
1628
1929
|
|
|
1629
|
-
|
|
1630
|
-
|
|
1930
|
+
material.polygonOffset = true;
|
|
1931
|
+
material.polygonOffsetFactor = 1;
|
|
1631
1932
|
|
|
1632
|
-
|
|
1933
|
+
if ( luminance !== 0 ) {
|
|
1633
1934
|
|
|
1634
|
-
|
|
1635
|
-
if ( fileName.startsWith( 's/' ) ) {
|
|
1935
|
+
material.emissive.set( material.color ).multiplyScalar( luminance );
|
|
1636
1936
|
|
|
1637
|
-
|
|
1937
|
+
}
|
|
1638
1938
|
|
|
1639
|
-
|
|
1939
|
+
if ( ! edgeMaterial ) {
|
|
1640
1940
|
|
|
1641
|
-
|
|
1941
|
+
// This is the material used for edges
|
|
1942
|
+
edgeMaterial = new LineBasicMaterial( {
|
|
1943
|
+
color: edgeColor,
|
|
1944
|
+
transparent: isTransparent,
|
|
1945
|
+
opacity: alpha,
|
|
1946
|
+
depthWrite: ! isTransparent
|
|
1947
|
+
} );
|
|
1948
|
+
edgeMaterial.userData.code = code;
|
|
1949
|
+
edgeMaterial.name = name + ' - Edge';
|
|
1642
1950
|
|
|
1643
|
-
|
|
1951
|
+
// This is the material used for conditional edges
|
|
1952
|
+
edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial( {
|
|
1644
1953
|
|
|
1645
|
-
|
|
1954
|
+
fog: true,
|
|
1955
|
+
transparent: isTransparent,
|
|
1956
|
+
depthWrite: ! isTransparent,
|
|
1957
|
+
color: edgeColor,
|
|
1958
|
+
opacity: alpha,
|
|
1646
1959
|
|
|
1647
|
-
|
|
1648
|
-
material: material,
|
|
1649
|
-
matrix: matrix,
|
|
1650
|
-
fileName: fileName,
|
|
1651
|
-
inverted: bfcInverted !== currentParseScope.inverted,
|
|
1652
|
-
startingConstructionStep: startingConstructionStep
|
|
1653
|
-
} );
|
|
1960
|
+
} );
|
|
1654
1961
|
|
|
1655
|
-
|
|
1962
|
+
}
|
|
1656
1963
|
|
|
1657
|
-
|
|
1964
|
+
material.userData.code = code;
|
|
1965
|
+
material.name = name;
|
|
1658
1966
|
|
|
1659
|
-
|
|
1660
|
-
case '2':
|
|
1967
|
+
material.userData.edgeMaterial = edgeMaterial;
|
|
1661
1968
|
|
|
1662
|
-
|
|
1663
|
-
v0 = parseVector( lp );
|
|
1664
|
-
v1 = parseVector( lp );
|
|
1969
|
+
return material;
|
|
1665
1970
|
|
|
1666
|
-
|
|
1667
|
-
material: material.userData.edgeMaterial,
|
|
1668
|
-
colourCode: material.userData.code,
|
|
1669
|
-
v0: v0,
|
|
1670
|
-
v1: v1,
|
|
1971
|
+
}
|
|
1671
1972
|
|
|
1672
|
-
|
|
1673
|
-
};
|
|
1973
|
+
//
|
|
1674
1974
|
|
|
1675
|
-
|
|
1975
|
+
objectParse( info, parseScope ) {
|
|
1676
1976
|
|
|
1677
|
-
|
|
1977
|
+
// Retrieve data from the parent parse scope
|
|
1978
|
+
const currentParseScope = parseScope;
|
|
1979
|
+
const parentParseScope = currentParseScope.parentScope;
|
|
1678
1980
|
|
|
1679
|
-
|
|
1680
|
-
|
|
1981
|
+
// Main color codes passed to this subobject (or default codes 16 and 24 if it is the root object)
|
|
1982
|
+
const mainColorCode = currentParseScope.mainColorCode;
|
|
1983
|
+
const mainEdgeColorCode = currentParseScope.mainEdgeColorCode;
|
|
1681
1984
|
|
|
1682
|
-
|
|
1683
|
-
v0 = parseVector( lp );
|
|
1684
|
-
v1 = parseVector( lp );
|
|
1685
|
-
c0 = parseVector( lp );
|
|
1686
|
-
c1 = parseVector( lp );
|
|
1985
|
+
const parseColorCode = ( colorCode, forEdge ) => {
|
|
1687
1986
|
|
|
1688
|
-
|
|
1689
|
-
material: material.userData.edgeMaterial.userData.conditionalEdgeMaterial,
|
|
1690
|
-
colourCode: material.userData.code,
|
|
1691
|
-
vertices: [ v0, v1 ],
|
|
1692
|
-
controlPoints: [ c0, c1 ],
|
|
1693
|
-
};
|
|
1987
|
+
// Parses next color code and returns a THREE.Material
|
|
1694
1988
|
|
|
1695
|
-
|
|
1989
|
+
if ( ! forEdge && colorCode === MAIN_COLOUR_CODE ) {
|
|
1696
1990
|
|
|
1697
|
-
|
|
1991
|
+
colorCode = mainColorCode;
|
|
1698
1992
|
|
|
1699
|
-
|
|
1700
|
-
case '3':
|
|
1993
|
+
}
|
|
1701
1994
|
|
|
1702
|
-
|
|
1995
|
+
if ( forEdge && colorCode === MAIN_EDGE_COLOUR_CODE ) {
|
|
1703
1996
|
|
|
1704
|
-
|
|
1705
|
-
ccw = bfcCCW !== inverted;
|
|
1706
|
-
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1997
|
+
colorCode = mainEdgeColorCode;
|
|
1707
1998
|
|
|
1708
|
-
|
|
1999
|
+
}
|
|
1709
2000
|
|
|
1710
|
-
|
|
1711
|
-
v1 = parseVector( lp );
|
|
1712
|
-
v2 = parseVector( lp );
|
|
2001
|
+
const material = this.getMaterial( colorCode, currentParseScope );
|
|
1713
2002
|
|
|
1714
|
-
|
|
2003
|
+
if ( ! material ) {
|
|
1715
2004
|
|
|
1716
|
-
|
|
1717
|
-
v1 = parseVector( lp );
|
|
1718
|
-
v0 = parseVector( lp );
|
|
2005
|
+
throw new Error( 'LDrawLoader: Unknown color code "' + colorCode + '" is used but it was not defined previously.' );
|
|
1719
2006
|
|
|
1720
|
-
|
|
2007
|
+
}
|
|
1721
2008
|
|
|
1722
|
-
|
|
1723
|
-
_tempVec1.subVectors( v2, v1 );
|
|
1724
|
-
faceNormal = new Vector3()
|
|
1725
|
-
.crossVectors( _tempVec0, _tempVec1 )
|
|
1726
|
-
.normalize();
|
|
2009
|
+
return material;
|
|
1727
2010
|
|
|
1728
|
-
|
|
1729
|
-
material: material,
|
|
1730
|
-
colourCode: material.userData.code,
|
|
1731
|
-
faceNormal: faceNormal,
|
|
1732
|
-
vertices: [ v0, v1, v2 ],
|
|
1733
|
-
normals: [ null, null, null ],
|
|
1734
|
-
} );
|
|
1735
|
-
currentParseScope.totalFaces ++;
|
|
2011
|
+
};
|
|
1736
2012
|
|
|
1737
|
-
|
|
2013
|
+
const faces = info.faces;
|
|
2014
|
+
const lineSegments = info.lineSegments;
|
|
2015
|
+
const conditionalSegments = info.conditionalSegments;
|
|
2016
|
+
const materials = info.materials;
|
|
2017
|
+
if ( currentParseScope.inverted ) {
|
|
1738
2018
|
|
|
1739
|
-
|
|
1740
|
-
material: material,
|
|
1741
|
-
colourCode: material.userData.code,
|
|
1742
|
-
faceNormal: faceNormal,
|
|
1743
|
-
vertices: [ v2, v1, v0 ],
|
|
1744
|
-
normals: [ null, null, null ],
|
|
1745
|
-
} );
|
|
1746
|
-
currentParseScope.totalFaces ++;
|
|
2019
|
+
faces.reverse();
|
|
1747
2020
|
|
|
1748
|
-
|
|
2021
|
+
}
|
|
1749
2022
|
|
|
1750
|
-
|
|
2023
|
+
for ( const colorCode in materials ) {
|
|
1751
2024
|
|
|
1752
|
-
|
|
1753
|
-
case '4':
|
|
2025
|
+
this.addMaterial( materials[ colorCode ], currentParseScope );
|
|
1754
2026
|
|
|
1755
|
-
|
|
2027
|
+
}
|
|
1756
2028
|
|
|
1757
|
-
|
|
1758
|
-
ccw = bfcCCW !== inverted;
|
|
1759
|
-
doubleSided = ! bfcCertified || ! bfcCull;
|
|
2029
|
+
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
1760
2030
|
|
|
1761
|
-
|
|
2031
|
+
const face = faces[ i ];
|
|
2032
|
+
if ( face.material === null ) {
|
|
1762
2033
|
|
|
1763
|
-
|
|
1764
|
-
v1 = parseVector( lp );
|
|
1765
|
-
v2 = parseVector( lp );
|
|
1766
|
-
v3 = parseVector( lp );
|
|
2034
|
+
face.material = parseColorCode( face.colorCode, false );
|
|
1767
2035
|
|
|
1768
|
-
|
|
2036
|
+
}
|
|
1769
2037
|
|
|
1770
|
-
|
|
1771
|
-
v2 = parseVector( lp );
|
|
1772
|
-
v1 = parseVector( lp );
|
|
1773
|
-
v0 = parseVector( lp );
|
|
2038
|
+
}
|
|
1774
2039
|
|
|
1775
|
-
|
|
2040
|
+
for ( let i = 0, l = lineSegments.length; i < l; i ++ ) {
|
|
1776
2041
|
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
faceNormal = new Vector3()
|
|
1780
|
-
.crossVectors( _tempVec0, _tempVec1 )
|
|
1781
|
-
.normalize();
|
|
2042
|
+
const ls = lineSegments[ i ];
|
|
2043
|
+
if ( ls.material === null ) {
|
|
1782
2044
|
|
|
1783
|
-
|
|
1784
|
-
// account for the doubling of vertices later when smoothing normals.
|
|
1785
|
-
faces.push( {
|
|
1786
|
-
material: material,
|
|
1787
|
-
colourCode: material.userData.code,
|
|
1788
|
-
faceNormal: faceNormal,
|
|
1789
|
-
vertices: [ v0, v1, v2, v3 ],
|
|
1790
|
-
normals: [ null, null, null, null ],
|
|
1791
|
-
} );
|
|
1792
|
-
currentParseScope.totalFaces += 2;
|
|
2045
|
+
ls.material = parseColorCode( ls.colorCode, true );
|
|
1793
2046
|
|
|
1794
|
-
|
|
2047
|
+
}
|
|
1795
2048
|
|
|
1796
|
-
|
|
1797
|
-
material: material,
|
|
1798
|
-
colourCode: material.userData.code,
|
|
1799
|
-
faceNormal: faceNormal,
|
|
1800
|
-
vertices: [ v3, v2, v1, v0 ],
|
|
1801
|
-
normals: [ null, null, null, null ],
|
|
1802
|
-
} );
|
|
1803
|
-
currentParseScope.totalFaces += 2;
|
|
2049
|
+
}
|
|
1804
2050
|
|
|
1805
|
-
|
|
2051
|
+
for ( let i = 0, l = conditionalSegments.length; i < l; i ++ ) {
|
|
1806
2052
|
|
|
1807
|
-
|
|
2053
|
+
const cs = conditionalSegments[ i ];
|
|
2054
|
+
if ( cs.material === null ) {
|
|
1808
2055
|
|
|
1809
|
-
|
|
1810
|
-
throw 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.';
|
|
1811
|
-
break;
|
|
2056
|
+
cs.material = parseColorCode( cs.colorCode, true );
|
|
1812
2057
|
|
|
1813
2058
|
}
|
|
1814
2059
|
|
|
1815
2060
|
}
|
|
1816
2061
|
|
|
1817
|
-
|
|
2062
|
+
currentParseScope.faces = info.faces;
|
|
2063
|
+
currentParseScope.conditionalSegments = info.conditionalSegments;
|
|
2064
|
+
currentParseScope.lineSegments = info.lineSegments;
|
|
2065
|
+
currentParseScope.category = info.category;
|
|
2066
|
+
currentParseScope.keywords = info.keywords;
|
|
2067
|
+
currentParseScope.subobjects = info.subobjects;
|
|
2068
|
+
currentParseScope.type = info.type;
|
|
2069
|
+
currentParseScope.totalFaces = info.totalFaces;
|
|
2070
|
+
|
|
2071
|
+
const isRoot = ! parentParseScope.isFromParse;
|
|
2072
|
+
if ( isRoot || ! isPrimitiveType( info.type ) ) {
|
|
1818
2073
|
|
|
1819
|
-
|
|
2074
|
+
currentParseScope.groupObject = new Group();
|
|
2075
|
+
currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep;
|
|
1820
2076
|
|
|
1821
2077
|
}
|
|
1822
2078
|
|
|
1823
|
-
currentParseScope.category = category;
|
|
1824
|
-
currentParseScope.keywords = keywords;
|
|
1825
|
-
currentParseScope.subobjects = subobjects;
|
|
1826
|
-
currentParseScope.numSubobjects = subobjects.length;
|
|
1827
|
-
currentParseScope.subobjectIndex = 0;
|
|
1828
|
-
|
|
1829
2079
|
}
|
|
1830
2080
|
|
|
1831
2081
|
computeConstructionSteps( model ) {
|
|
@@ -1856,6 +2106,13 @@ class LDrawLoader extends Loader {
|
|
|
1856
2106
|
|
|
1857
2107
|
finalizeObject( subobjectParseScope ) {
|
|
1858
2108
|
|
|
2109
|
+
// fail gracefully if an object could not be loaded
|
|
2110
|
+
if ( subobjectParseScope === null ) {
|
|
2111
|
+
|
|
2112
|
+
return;
|
|
2113
|
+
|
|
2114
|
+
}
|
|
2115
|
+
|
|
1859
2116
|
const parentParseScope = subobjectParseScope.parentScope;
|
|
1860
2117
|
|
|
1861
2118
|
// Smooth the normals if this is a part or if this is a case where the subpart
|
|
@@ -1864,19 +2121,23 @@ class LDrawLoader extends Loader {
|
|
|
1864
2121
|
const doSmooth =
|
|
1865
2122
|
isPartType( subobjectParseScope.type ) ||
|
|
1866
2123
|
(
|
|
1867
|
-
|
|
1868
|
-
! isModelType( subobjectParseScope.type ) &&
|
|
2124
|
+
isPrimitiveType( subobjectParseScope.type ) &&
|
|
1869
2125
|
isModelType( subobjectParseScope.parentScope.type )
|
|
1870
2126
|
);
|
|
1871
2127
|
|
|
1872
2128
|
if ( this.smoothNormals && doSmooth ) {
|
|
1873
2129
|
|
|
1874
|
-
|
|
2130
|
+
generateFaceNormals( subobjectParseScope.faces );
|
|
2131
|
+
|
|
2132
|
+
// only check subsetgments if we have multiple materials in a single part because this seems to be the case where it's needed most --
|
|
2133
|
+
// there may be cases where a single edge line crosses over polygon edges that are broken up by multiple materials.
|
|
2134
|
+
const checkSubSegments = subobjectParseScope.faceMaterials.size > 1;
|
|
2135
|
+
smoothNormals( subobjectParseScope.faces, subobjectParseScope.lineSegments, checkSubSegments );
|
|
1875
2136
|
|
|
1876
2137
|
}
|
|
1877
2138
|
|
|
1878
2139
|
const isRoot = ! parentParseScope.isFromParse;
|
|
1879
|
-
if (
|
|
2140
|
+
if ( ! isPrimitiveType( subobjectParseScope.type ) || isRoot ) {
|
|
1880
2141
|
|
|
1881
2142
|
const objGroup = subobjectParseScope.groupObject;
|
|
1882
2143
|
|
|
@@ -1911,26 +2172,24 @@ class LDrawLoader extends Loader {
|
|
|
1911
2172
|
|
|
1912
2173
|
} else {
|
|
1913
2174
|
|
|
1914
|
-
const separateObjects = this.separateObjects;
|
|
1915
2175
|
const parentLineSegments = parentParseScope.lineSegments;
|
|
1916
2176
|
const parentConditionalSegments = parentParseScope.conditionalSegments;
|
|
1917
2177
|
const parentFaces = parentParseScope.faces;
|
|
2178
|
+
const parentFaceMaterials = parentParseScope.faceMaterials;
|
|
1918
2179
|
|
|
1919
2180
|
const lineSegments = subobjectParseScope.lineSegments;
|
|
1920
2181
|
const conditionalSegments = subobjectParseScope.conditionalSegments;
|
|
1921
2182
|
const faces = subobjectParseScope.faces;
|
|
2183
|
+
const faceMaterials = subobjectParseScope.faceMaterials;
|
|
2184
|
+
const matrix = subobjectParseScope.matrix;
|
|
2185
|
+
const matrixScaleInverted = matrix.determinant() < 0;
|
|
1922
2186
|
|
|
1923
2187
|
for ( let i = 0, l = lineSegments.length; i < l; i ++ ) {
|
|
1924
2188
|
|
|
1925
2189
|
const ls = lineSegments[ i ];
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
const vertices = ls.vertices;
|
|
1930
|
-
vertices[ 0 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1931
|
-
vertices[ 1 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1932
|
-
|
|
1933
|
-
}
|
|
2190
|
+
const vertices = ls.vertices;
|
|
2191
|
+
vertices[ 0 ].applyMatrix4( matrix );
|
|
2192
|
+
vertices[ 1 ].applyMatrix4( matrix );
|
|
1934
2193
|
|
|
1935
2194
|
parentLineSegments.push( ls );
|
|
1936
2195
|
|
|
@@ -1939,17 +2198,12 @@ class LDrawLoader extends Loader {
|
|
|
1939
2198
|
for ( let i = 0, l = conditionalSegments.length; i < l; i ++ ) {
|
|
1940
2199
|
|
|
1941
2200
|
const os = conditionalSegments[ i ];
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
vertices[ 1 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1949
|
-
controlPoints[ 0 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1950
|
-
controlPoints[ 1 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1951
|
-
|
|
1952
|
-
}
|
|
2201
|
+
const vertices = os.vertices;
|
|
2202
|
+
const controlPoints = os.controlPoints;
|
|
2203
|
+
vertices[ 0 ].applyMatrix4( matrix );
|
|
2204
|
+
vertices[ 1 ].applyMatrix4( matrix );
|
|
2205
|
+
controlPoints[ 0 ].applyMatrix4( matrix );
|
|
2206
|
+
controlPoints[ 1 ].applyMatrix4( matrix );
|
|
1953
2207
|
|
|
1954
2208
|
parentConditionalSegments.push( os );
|
|
1955
2209
|
|
|
@@ -1958,19 +2212,18 @@ class LDrawLoader extends Loader {
|
|
|
1958
2212
|
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
1959
2213
|
|
|
1960
2214
|
const tri = faces[ i ];
|
|
2215
|
+
const vertices = tri.vertices;
|
|
2216
|
+
for ( let i = 0, l = vertices.length; i < l; i ++ ) {
|
|
1961
2217
|
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
const vertices = tri.vertices;
|
|
1965
|
-
for ( let i = 0, l = vertices.length; i < l; i ++ ) {
|
|
2218
|
+
vertices[ i ].applyMatrix4( matrix );
|
|
1966
2219
|
|
|
1967
|
-
|
|
2220
|
+
}
|
|
1968
2221
|
|
|
1969
|
-
|
|
2222
|
+
// If the scale of the object is negated then the triangle winding order
|
|
2223
|
+
// needs to be flipped.
|
|
2224
|
+
if ( matrixScaleInverted !== subobjectParseScope.inverted ) {
|
|
1970
2225
|
|
|
1971
|
-
|
|
1972
|
-
_tempVec1.subVectors( vertices[ 2 ], vertices[ 1 ] );
|
|
1973
|
-
tri.faceNormal.crossVectors( _tempVec0, _tempVec1 ).normalize();
|
|
2226
|
+
vertices.reverse();
|
|
1974
2227
|
|
|
1975
2228
|
}
|
|
1976
2229
|
|
|
@@ -1979,41 +2232,48 @@ class LDrawLoader extends Loader {
|
|
|
1979
2232
|
}
|
|
1980
2233
|
|
|
1981
2234
|
parentParseScope.totalFaces += subobjectParseScope.totalFaces;
|
|
2235
|
+
faceMaterials.forEach( material => parentFaceMaterials.add( material ) );
|
|
1982
2236
|
|
|
1983
2237
|
}
|
|
1984
2238
|
|
|
1985
2239
|
}
|
|
1986
2240
|
|
|
1987
|
-
async processObject(
|
|
2241
|
+
async processObject( parsedInfo, subobject, url, parentScope ) {
|
|
1988
2242
|
|
|
1989
2243
|
const scope = this;
|
|
1990
2244
|
|
|
1991
2245
|
const parseScope = this.newParseScopeLevel( null, parentScope );
|
|
1992
2246
|
parseScope.url = url;
|
|
1993
2247
|
|
|
1994
|
-
const parentParseScope = parseScope.parentScope;
|
|
1995
|
-
|
|
1996
2248
|
// Set current matrix
|
|
1997
2249
|
if ( subobject ) {
|
|
1998
2250
|
|
|
1999
|
-
parseScope.currentMatrix.multiplyMatrices( parentParseScope.currentMatrix, subobject.matrix );
|
|
2000
2251
|
parseScope.matrix.copy( subobject.matrix );
|
|
2001
2252
|
parseScope.inverted = subobject.inverted;
|
|
2002
2253
|
parseScope.startingConstructionStep = subobject.startingConstructionStep;
|
|
2003
|
-
parseScope.mainColourCode = subobject.material.userData.code;
|
|
2004
|
-
parseScope.mainEdgeColourCode = subobject.material.userData.edgeMaterial.userData.code;
|
|
2005
2254
|
parseScope.fileName = subobject.fileName;
|
|
2255
|
+
if ( subobject.colorCode === MAIN_COLOUR_CODE && parentScope ) {
|
|
2256
|
+
|
|
2257
|
+
parseScope.mainColorCode = parentScope.mainColorCode;
|
|
2258
|
+
parseScope.mainEdgeColorCode = parentScope.mainEdgeColorCode;
|
|
2259
|
+
|
|
2260
|
+
} else if ( subobject.colorCode !== MAIN_COLOUR_CODE ) {
|
|
2261
|
+
|
|
2262
|
+
parseScope.mainColorCode = subobject.colorCode;
|
|
2263
|
+
parseScope.mainEdgeColorCode = subobject.colorCode;
|
|
2264
|
+
|
|
2265
|
+
}
|
|
2006
2266
|
|
|
2007
2267
|
}
|
|
2008
2268
|
|
|
2009
2269
|
// Parse the object
|
|
2010
|
-
this.objectParse(
|
|
2270
|
+
this.objectParse( parsedInfo, parseScope );
|
|
2011
2271
|
|
|
2012
2272
|
const subobjects = parseScope.subobjects;
|
|
2013
2273
|
const promises = [];
|
|
2014
2274
|
for ( let i = 0, l = subobjects.length; i < l; i ++ ) {
|
|
2015
2275
|
|
|
2016
|
-
promises.push( loadSubobject(
|
|
2276
|
+
promises.push( loadSubobject( subobjects[ i ] ) );
|
|
2017
2277
|
|
|
2018
2278
|
}
|
|
2019
2279
|
|
|
@@ -2027,7 +2287,7 @@ class LDrawLoader extends Loader {
|
|
|
2027
2287
|
}
|
|
2028
2288
|
|
|
2029
2289
|
// If it is root object then finalize this object and compute construction steps
|
|
2030
|
-
if ( !
|
|
2290
|
+
if ( ! parentScope.isFromParse ) {
|
|
2031
2291
|
|
|
2032
2292
|
this.finalizeObject( parseScope );
|
|
2033
2293
|
this.computeConstructionSteps( parseScope.groupObject );
|
|
@@ -2038,13 +2298,14 @@ class LDrawLoader extends Loader {
|
|
|
2038
2298
|
|
|
2039
2299
|
function loadSubobject( subobject ) {
|
|
2040
2300
|
|
|
2041
|
-
return scope.
|
|
2301
|
+
return scope.parseCache.loadData( subobject.fileName ).then( function ( parsedInfo ) {
|
|
2042
2302
|
|
|
2043
|
-
return scope.processObject(
|
|
2303
|
+
return scope.processObject( parsedInfo, subobject, url, parseScope );
|
|
2044
2304
|
|
|
2045
|
-
} ).catch( function () {
|
|
2305
|
+
} ).catch( function ( err ) {
|
|
2046
2306
|
|
|
2047
|
-
console.warn(
|
|
2307
|
+
console.warn( err );
|
|
2308
|
+
return null;
|
|
2048
2309
|
|
|
2049
2310
|
} );
|
|
2050
2311
|
|