super-three 0.136.0 → 0.141.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +24 -26
- package/build/three.cjs +35889 -0
- package/build/three.js +4837 -6036
- package/build/three.min.js +2 -2
- package/build/three.module.js +16548 -17930
- package/examples/js/animation/CCDIKSolver.js +3 -2
- package/examples/js/animation/MMDAnimationHelper.js +3 -1
- package/examples/js/animation/MMDPhysics.js +3 -3
- package/examples/js/cameras/CinematicCamera.js +2 -7
- package/examples/js/controls/ArcballControls.js +3 -1
- package/examples/js/controls/PointerLockControls.js +3 -2
- package/examples/js/controls/TrackballControls.js +1 -4
- package/examples/js/controls/TransformControls.js +5 -6
- package/examples/js/controls/experimental/CameraControls.js +8 -4
- package/examples/js/csm/CSMFrustum.js +1 -1
- package/examples/js/csm/CSMShader.js +51 -35
- package/examples/js/curves/CurveExtras.js +14 -18
- package/examples/js/effects/AnaglyphEffect.js +7 -4
- package/examples/js/effects/AsciiEffect.js +10 -29
- package/examples/js/exporters/ColladaExporter.js +29 -7
- package/examples/js/exporters/EXRExporter.js +458 -0
- package/examples/js/exporters/GLTFExporter.js +233 -105
- package/examples/js/exporters/MMDExporter.js +1 -1
- package/examples/js/exporters/OBJExporter.js +12 -18
- package/examples/js/exporters/PLYExporter.js +15 -20
- package/examples/js/exporters/USDZExporter.js +13 -0
- package/examples/js/geometries/ConvexGeometry.js +1 -1
- package/examples/js/geometries/DecalGeometry.js +0 -7
- package/examples/js/geometries/LightningStrike.js +2 -2
- package/examples/js/geometries/ParametricGeometries.js +3 -3
- package/examples/js/geometries/TextGeometry.js +12 -10
- package/examples/js/helpers/OctreeHelper.js +74 -0
- package/examples/js/helpers/VertexNormalsHelper.js +4 -23
- package/examples/js/helpers/VertexTangentsHelper.js +3 -13
- package/examples/js/helpers/ViewHelper.js +266 -0
- package/examples/js/interactive/HTMLMesh.js +249 -42
- package/examples/js/interactive/SelectionHelper.js +1 -1
- package/examples/js/libs/opentype.min.js +1 -118
- package/examples/js/lines/Line2.js +1 -2
- package/examples/js/lines/LineGeometry.js +10 -21
- package/examples/js/lines/LineMaterial.js +2 -3
- package/examples/js/lines/LineSegments2.js +214 -140
- package/examples/js/lines/LineSegmentsGeometry.js +3 -14
- package/examples/js/lines/Wireframe.js +2 -3
- package/examples/js/lines/WireframeGeometry2.js +1 -2
- package/examples/js/loaders/3MFLoader.js +21 -17
- package/examples/js/loaders/AMFLoader.js +1 -1
- package/examples/js/loaders/BasisTextureLoader.js +1 -0
- package/examples/js/loaders/ColladaLoader.js +33 -12
- package/examples/js/loaders/DDSLoader.js +23 -30
- package/examples/js/loaders/EXRLoader.js +314 -294
- package/examples/js/loaders/FBXLoader.js +11 -0
- package/examples/js/loaders/FontLoader.js +1 -2
- package/examples/js/loaders/GCodeLoader.js +0 -1
- package/examples/js/loaders/GLTFLoader.js +250 -61
- package/examples/js/loaders/HDRCubeTextureLoader.js +0 -2
- package/examples/js/loaders/KMZLoader.js +1 -1
- package/examples/js/loaders/KTX2Loader.js +1 -9
- package/examples/js/loaders/LDrawLoader.js +1342 -962
- package/examples/js/loaders/LUT3dlLoader.js +18 -11
- package/examples/js/loaders/LUTCubeLoader.js +4 -5
- package/examples/js/loaders/LWOLoader.js +4 -2
- package/examples/js/loaders/LogLuvLoader.js +1 -2
- package/examples/js/loaders/MD2Loader.js +5 -5
- package/examples/js/loaders/MMDLoader.js +18 -4
- package/examples/js/loaders/MTLLoader.js +10 -3
- package/examples/js/loaders/NRRDLoader.js +1 -1
- package/examples/js/loaders/OBJLoader.js +9 -5
- package/examples/js/loaders/PCDLoader.js +24 -15
- package/examples/js/loaders/PDBLoader.js +11 -11
- package/examples/js/loaders/PLYLoader.js +5 -1
- package/examples/js/loaders/RGBELoader.js +9 -17
- package/examples/js/loaders/RGBMLoader.js +13 -16
- package/examples/js/loaders/STLLoader.js +1 -1
- package/examples/js/loaders/SVGLoader.js +21 -11
- package/examples/js/loaders/VOXLoader.js +3 -4
- package/examples/js/loaders/VRMLLoader.js +9 -21
- package/examples/js/loaders/VTKLoader.js +260 -295
- package/examples/js/loaders/lwo/LWO2Parser.js +4 -4
- package/examples/js/loaders/lwo/LWO3Parser.js +4 -4
- package/examples/js/math/ConvexHull.js +13 -28
- package/examples/js/math/Lut.js +27 -26
- package/examples/js/misc/MorphAnimMesh.js +2 -2
- package/examples/js/misc/ProgressiveLightMap.js +1 -1
- package/examples/js/misc/Volume.js +39 -48
- package/examples/js/misc/VolumeSlice.js +21 -21
- package/examples/js/modifiers/CurveModifier.js +8 -7
- package/examples/js/modifiers/EdgeSplitModifier.js +0 -13
- package/examples/js/modifiers/SimplifyModifier.js +1 -18
- package/examples/js/modifiers/TessellateModifier.js +0 -7
- package/examples/js/objects/Lensflare.js +4 -4
- package/examples/js/objects/LightningStorm.js +4 -5
- package/examples/js/objects/MarchingCubes.js +6 -11
- package/examples/js/objects/Reflector.js +10 -16
- package/examples/js/objects/ReflectorForSSRPass.js +1 -11
- package/examples/js/objects/Refractor.js +10 -16
- package/examples/js/objects/ShadowMesh.js +1 -2
- package/examples/js/objects/Sky.js +1 -1
- package/examples/js/objects/Water.js +2 -15
- package/examples/js/objects/Water2.js +1 -1
- package/examples/js/postprocessing/AdaptiveToneMappingPass.js +6 -10
- package/examples/js/postprocessing/AfterimagePass.js +2 -6
- package/examples/js/postprocessing/BloomPass.js +50 -19
- package/examples/js/postprocessing/DotScreenPass.js +1 -1
- package/examples/js/postprocessing/EffectComposer.js +1 -6
- package/examples/js/postprocessing/GlitchPass.js +4 -5
- package/examples/js/postprocessing/LUTPass.js +2 -2
- package/examples/js/postprocessing/OutlinePass.js +8 -17
- package/examples/js/postprocessing/SAOPass.js +2 -7
- package/examples/js/postprocessing/SMAAPass.js +2 -9
- package/examples/js/postprocessing/SSAARenderPass.js +1 -6
- package/examples/js/postprocessing/SSAOPass.js +9 -21
- package/examples/js/postprocessing/SSRPass.js +3 -8
- package/examples/js/postprocessing/SavePass.js +1 -5
- package/examples/js/postprocessing/TAARenderPass.js +4 -4
- package/examples/js/postprocessing/UnrealBloomPass.js +3 -12
- package/examples/js/renderers/CSS2DRenderer.js +20 -19
- package/examples/js/renderers/CSS3DRenderer.js +40 -36
- package/examples/js/renderers/Projector.js +97 -124
- package/examples/js/renderers/SVGRenderer.js +3 -4
- package/examples/js/shaders/BlendShader.js +2 -1
- package/examples/js/shaders/CopyShader.js +4 -3
- package/examples/js/shaders/DigitalGlitch.js +3 -3
- package/examples/js/shaders/FXAAShader.js +239 -1069
- package/examples/js/shaders/FreiChenShader.js +1 -1
- package/examples/js/shaders/HorizontalBlurShader.js +1 -1
- package/examples/js/shaders/HorizontalTiltShiftShader.js +1 -1
- package/examples/js/shaders/MMDToonShader.js +0 -1
- package/examples/js/shaders/SSAOShader.js +1 -1
- package/examples/js/shaders/SSRShader.js +3 -3
- package/examples/js/shaders/ToneMapShader.js +1 -1
- package/examples/js/utils/BufferGeometryUtils.js +282 -22
- package/examples/js/utils/GPUStatsPanel.js +1 -1
- package/examples/js/utils/LDrawUtils.js +182 -0
- package/examples/js/utils/SceneUtils.js +59 -0
- package/examples/js/utils/SkeletonUtils.js +1 -1
- package/examples/js/utils/UVsDebug.js +23 -33
- package/examples/jsm/animation/CCDIKSolver.js +3 -9
- package/examples/jsm/animation/MMDPhysics.js +2 -2
- 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 +7 -1
- package/examples/jsm/controls/ArcballControls.js +3 -1
- package/examples/jsm/controls/PointerLockControls.js +4 -2
- package/examples/jsm/controls/TrackballControls.js +1 -4
- package/examples/jsm/controls/TransformControls.js +6 -6
- package/examples/jsm/controls/experimental/CameraControls.js +2 -2
- package/examples/jsm/csm/CSMFrustum.js +1 -1
- package/examples/jsm/csm/CSMShader.js +51 -35
- package/examples/jsm/curves/CurveExtras.js +15 -17
- package/examples/jsm/effects/AnaglyphEffect.js +4 -4
- package/examples/jsm/effects/AsciiEffect.js +9 -22
- package/examples/jsm/exporters/ColladaExporter.js +31 -6
- package/examples/jsm/exporters/EXRExporter.js +507 -0
- package/examples/jsm/exporters/GLTFExporter.js +261 -103
- package/examples/jsm/exporters/KTX2Exporter.js +281 -0
- package/examples/jsm/exporters/MMDExporter.js +1 -1
- package/examples/jsm/exporters/OBJExporter.js +11 -18
- package/examples/jsm/exporters/PLYExporter.js +23 -21
- package/examples/jsm/exporters/USDZExporter.js +12 -0
- package/examples/jsm/geometries/ConvexGeometry.js +1 -1
- package/examples/jsm/geometries/DecalGeometry.js +0 -7
- package/examples/jsm/geometries/LightningStrike.js +2 -2
- package/examples/jsm/geometries/ParametricGeometries.js +3 -3
- package/examples/jsm/geometries/TextGeometry.js +13 -13
- package/examples/jsm/helpers/OctreeHelper.js +58 -0
- package/examples/jsm/helpers/VertexNormalsHelper.js +4 -25
- package/examples/jsm/helpers/VertexTangentsHelper.js +3 -15
- package/examples/jsm/helpers/ViewHelper.js +295 -0
- package/examples/jsm/interactive/HTMLMesh.js +268 -36
- package/examples/jsm/interactive/SelectionHelper.js +1 -1
- package/examples/jsm/libs/flow.module.js +947 -183
- package/examples/jsm/libs/ktx-parse.module.js +1 -1
- package/examples/jsm/libs/lil-gui.module.min.js +2 -2
- package/examples/jsm/libs/mikktspace.module.js +128 -0
- package/examples/jsm/libs/opentype.module.js +14568 -0
- package/examples/jsm/lines/Line2.js +2 -2
- package/examples/jsm/lines/LineGeometry.js +11 -19
- package/examples/jsm/lines/LineMaterial.js +3 -3
- package/examples/jsm/lines/LineSegments2.js +210 -145
- package/examples/jsm/lines/LineSegmentsGeometry.js +3 -12
- package/examples/jsm/lines/Wireframe.js +3 -3
- package/examples/jsm/lines/WireframeGeometry2.js +2 -2
- package/examples/jsm/loaders/3DMLoader.js +3 -2
- package/examples/jsm/loaders/3MFLoader.js +21 -17
- package/examples/jsm/loaders/AMFLoader.js +1 -1
- package/examples/jsm/loaders/BasisTextureLoader.js +7 -0
- package/examples/jsm/loaders/ColladaLoader.js +40 -12
- package/examples/jsm/loaders/DDSLoader.js +21 -28
- package/examples/jsm/loaders/EXRLoader.js +309 -293
- package/examples/jsm/loaders/FBXLoader.js +11 -0
- package/examples/jsm/loaders/FontLoader.js +2 -2
- package/examples/jsm/loaders/GCodeLoader.js +0 -1
- package/examples/jsm/loaders/GLTFLoader.js +263 -68
- package/examples/jsm/loaders/HDRCubeTextureLoader.js +1 -4
- package/examples/jsm/loaders/KMZLoader.js +1 -1
- package/examples/jsm/loaders/KTX2Loader.js +1 -10
- package/examples/jsm/loaders/LDrawLoader.js +1335 -988
- package/examples/jsm/loaders/LUT3dlLoader.js +19 -14
- package/examples/jsm/loaders/LUTCubeLoader.js +5 -7
- package/examples/jsm/loaders/LWOLoader.js +5 -3
- package/examples/jsm/loaders/LogLuvLoader.js +2 -2
- package/examples/jsm/loaders/MD2Loader.js +5 -5
- package/examples/jsm/loaders/MMDLoader.js +21 -3
- package/examples/jsm/loaders/MTLLoader.js +11 -4
- package/examples/jsm/loaders/NRRDLoader.js +1 -2
- package/examples/jsm/loaders/OBJLoader.js +11 -7
- package/examples/jsm/loaders/PCDLoader.js +25 -17
- package/examples/jsm/loaders/PDBLoader.js +11 -11
- package/examples/jsm/loaders/PLYLoader.js +10 -2
- package/examples/jsm/loaders/RGBELoader.js +11 -20
- package/examples/jsm/loaders/RGBMLoader.js +15 -12
- package/examples/jsm/loaders/STLLoader.js +1 -1
- package/examples/jsm/loaders/SVGLoader.js +26 -11
- package/examples/jsm/loaders/TTFLoader.js +1 -1
- package/examples/jsm/loaders/VOXLoader.js +5 -5
- package/examples/jsm/loaders/VRMLLoader.js +9 -23
- package/examples/jsm/loaders/VTKLoader.js +256 -284
- package/examples/jsm/loaders/ifc/web-ifc-api.js +9 -8
- package/examples/jsm/loaders/lwo/LWO2Parser.js +4 -4
- package/examples/jsm/loaders/lwo/LWO3Parser.js +4 -4
- package/examples/jsm/math/ConvexHull.js +13 -28
- package/examples/jsm/math/Lut.js +35 -25
- package/examples/jsm/misc/MorphAnimMesh.js +2 -2
- package/examples/jsm/misc/ProgressiveLightMap.js +1 -1
- package/examples/jsm/misc/Volume.js +39 -46
- package/examples/jsm/misc/VolumeSlice.js +21 -21
- package/examples/jsm/modifiers/CurveModifier.js +9 -8
- package/examples/jsm/modifiers/EdgeSplitModifier.js +0 -13
- package/examples/jsm/modifiers/SimplifyModifier.js +1 -18
- package/examples/jsm/modifiers/TessellateModifier.js +0 -7
- package/examples/jsm/node-editor/NodeEditor.js +485 -163
- package/examples/jsm/node-editor/accessors/MatcapUVEditor.js +14 -0
- package/examples/jsm/node-editor/accessors/NormalEditor.js +9 -9
- package/examples/jsm/node-editor/accessors/PositionEditor.js +9 -9
- package/examples/jsm/node-editor/accessors/UVEditor.js +7 -8
- package/examples/jsm/node-editor/core/BaseNode.js +89 -0
- package/examples/jsm/node-editor/core/DataFile.js +59 -0
- package/examples/jsm/node-editor/core/FileEditor.js +20 -0
- package/examples/jsm/node-editor/core/FileURLEditor.js +29 -0
- package/examples/jsm/node-editor/display/BlendEditor.js +10 -9
- package/examples/jsm/node-editor/display/NormalMapEditor.js +49 -0
- package/examples/jsm/node-editor/examples/animate-uv.json +1 -1
- package/examples/jsm/node-editor/examples/fake-top-light.json +1 -1
- package/examples/jsm/node-editor/examples/matcap.json +1 -0
- package/examples/jsm/node-editor/examples/oscillator-color.json +1 -1
- package/examples/jsm/node-editor/examples/rim.json +1 -1
- package/examples/jsm/node-editor/inputs/ColorEditor.js +18 -13
- package/examples/jsm/node-editor/inputs/FloatEditor.js +8 -9
- package/examples/jsm/node-editor/inputs/SliderEditor.js +6 -7
- package/examples/jsm/node-editor/inputs/TextureEditor.js +155 -0
- package/examples/jsm/node-editor/inputs/Vector2Editor.js +9 -9
- package/examples/jsm/node-editor/inputs/Vector3Editor.js +11 -11
- package/examples/jsm/node-editor/inputs/Vector4Editor.js +12 -12
- package/examples/jsm/node-editor/materials/BasicMaterialEditor.js +87 -0
- package/examples/jsm/node-editor/materials/PointsMaterialEditor.js +102 -0
- package/examples/jsm/node-editor/materials/StandardMaterialEditor.js +31 -18
- package/examples/jsm/node-editor/math/AngleEditor.js +40 -0
- package/examples/jsm/node-editor/math/DotEditor.js +8 -9
- package/examples/jsm/node-editor/math/InvertEditor.js +8 -7
- package/examples/jsm/node-editor/math/LimiterEditor.js +28 -14
- package/examples/jsm/node-editor/math/NormalizeEditor.js +9 -7
- package/examples/jsm/node-editor/math/OperatorEditor.js +29 -16
- package/examples/jsm/node-editor/math/PowerEditor.js +20 -10
- package/examples/jsm/node-editor/math/TrigonometryEditor.js +15 -9
- package/examples/jsm/node-editor/procedural/CheckerEditor.js +7 -6
- package/examples/jsm/node-editor/scene/MeshEditor.js +99 -0
- package/examples/jsm/node-editor/scene/Object3DEditor.js +160 -0
- package/examples/jsm/node-editor/scene/PointsEditor.js +99 -0
- package/examples/jsm/node-editor/utils/JoinEditor.js +58 -0
- package/examples/jsm/node-editor/utils/OscillatorEditor.js +9 -8
- package/examples/jsm/node-editor/utils/PreviewEditor.js +166 -0
- package/examples/jsm/node-editor/utils/SplitEditor.js +39 -0
- package/examples/jsm/node-editor/utils/TimerEditor.js +7 -6
- package/examples/jsm/nodes/Nodes.js +283 -94
- package/examples/jsm/nodes/accessors/BufferNode.js +24 -0
- package/examples/jsm/nodes/accessors/CameraNode.js +27 -196
- package/examples/jsm/nodes/accessors/CubeTextureNode.js +103 -0
- package/examples/jsm/nodes/accessors/InstanceNode.js +58 -0
- package/examples/jsm/{renderers/nodes → nodes}/accessors/MaterialNode.js +49 -11
- package/examples/jsm/{renderers/nodes → nodes}/accessors/MaterialReferenceNode.js +0 -0
- package/examples/jsm/{renderers/nodes → nodes}/accessors/ModelNode.js +8 -0
- package/examples/jsm/{renderers/nodes → nodes}/accessors/ModelViewProjectionNode.js +0 -0
- package/examples/jsm/nodes/accessors/NormalNode.js +39 -99
- package/examples/jsm/{renderers/nodes → nodes}/accessors/Object3DNode.js +34 -17
- package/examples/jsm/{renderers/nodes → nodes}/accessors/PointUVNode.js +2 -2
- package/examples/jsm/nodes/accessors/PositionNode.js +41 -110
- package/examples/jsm/nodes/accessors/ReferenceNode.js +65 -0
- package/examples/jsm/nodes/accessors/ReflectNode.js +34 -121
- package/examples/jsm/nodes/accessors/SkinningNode.js +102 -0
- package/examples/jsm/nodes/accessors/StorageBufferNode.js +21 -0
- package/examples/jsm/nodes/accessors/TextureNode.js +100 -0
- package/examples/jsm/nodes/accessors/UVNode.js +17 -43
- package/examples/jsm/nodes/accessors/UserDataNode.js +23 -0
- package/examples/jsm/nodes/core/ArrayUniformNode.js +23 -0
- package/examples/jsm/nodes/core/AttributeNode.js +33 -30
- package/examples/jsm/{renderers/nodes → nodes}/core/BypassNode.js +2 -2
- package/examples/jsm/{renderers/nodes → nodes}/core/CodeNode.js +2 -30
- package/examples/jsm/nodes/core/ConstNode.js +10 -106
- package/examples/jsm/{renderers/nodes → nodes}/core/ContextNode.js +17 -3
- package/examples/jsm/nodes/core/ExpressionNode.js +24 -7
- package/examples/jsm/nodes/core/FunctionCallNode.js +26 -67
- package/examples/jsm/nodes/core/FunctionNode.js +43 -216
- package/examples/jsm/nodes/core/InputNode.js +28 -60
- package/examples/jsm/nodes/core/InstanceIndexNode.js +21 -0
- package/examples/jsm/nodes/core/Node.js +228 -94
- package/examples/jsm/{renderers/nodes → nodes}/core/NodeAttribute.js +2 -2
- package/examples/jsm/nodes/core/NodeBuilder.js +388 -560
- package/examples/jsm/{renderers/nodes → nodes}/core/NodeCode.js +0 -0
- package/examples/jsm/nodes/core/NodeFrame.js +30 -23
- package/examples/jsm/{renderers/nodes → nodes}/core/NodeFunction.js +0 -0
- package/examples/jsm/{renderers/nodes → nodes}/core/NodeFunctionInput.js +0 -0
- package/examples/jsm/{renderers/nodes → nodes}/core/NodeKeywords.js +0 -0
- package/examples/jsm/{renderers/nodes → nodes}/core/NodeParser.js +0 -0
- package/examples/jsm/nodes/core/NodeUniform.js +8 -6
- package/examples/jsm/nodes/core/NodeUtils.js +69 -37
- package/examples/jsm/{renderers/nodes → nodes}/core/NodeVar.js +2 -2
- package/examples/jsm/{renderers/nodes → nodes}/core/NodeVary.js +2 -2
- package/examples/jsm/{renderers/nodes → nodes}/core/PropertyNode.js +0 -0
- package/examples/jsm/nodes/core/TempNode.js +20 -112
- package/examples/jsm/nodes/core/UniformNode.js +46 -0
- package/examples/jsm/nodes/core/VarNode.js +58 -27
- package/examples/jsm/{renderers/nodes → nodes}/core/VaryNode.js +0 -0
- package/examples/jsm/{renderers/nodes → nodes}/core/constants.js +0 -0
- package/examples/jsm/nodes/display/ColorSpaceNode.js +95 -0
- package/examples/jsm/nodes/display/FrontFacingNode.js +21 -0
- package/examples/jsm/nodes/display/NormalMapNode.js +86 -0
- package/examples/jsm/nodes/display/ToneMappingNode.js +51 -0
- package/examples/jsm/nodes/fog/FogNode.js +31 -0
- package/examples/jsm/nodes/fog/FogRangeNode.js +27 -0
- package/examples/jsm/nodes/functions/BSDF/BRDF_GGX.js +33 -0
- package/examples/jsm/nodes/functions/BSDF/BRDF_Lambert.js +9 -0
- package/examples/jsm/nodes/functions/BSDF/DFGApprox.js +27 -0
- package/examples/jsm/nodes/functions/BSDF/D_GGX.js +18 -0
- package/examples/jsm/nodes/functions/BSDF/F_Schlick.js +18 -0
- package/examples/jsm/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +18 -0
- package/examples/jsm/nodes/functions/PhysicalLightingModel.js +94 -0
- package/examples/jsm/nodes/functions/light/getDistanceAttenuation.js +22 -0
- package/examples/jsm/nodes/functions/material/getGeometryRoughness.js +12 -0
- package/examples/jsm/nodes/functions/material/getRoughness.js +18 -0
- package/examples/jsm/nodes/gpgpu/ComputeNode.js +63 -0
- package/examples/jsm/nodes/lighting/AONode.js +25 -0
- package/examples/jsm/nodes/lighting/AnalyticLightNode.js +37 -0
- package/examples/jsm/nodes/lighting/EnvironmentNode.js +65 -0
- package/examples/jsm/nodes/lighting/HemisphereLightNode.js +50 -0
- package/examples/jsm/nodes/lighting/LightingContextNode.js +75 -0
- package/examples/jsm/nodes/lighting/LightingNode.js +19 -0
- package/examples/jsm/nodes/lighting/LightsNode.js +120 -0
- package/examples/jsm/nodes/lighting/PunctualLightNode.js +68 -0
- package/examples/jsm/nodes/loaders/NodeLoader.js +107 -0
- package/examples/jsm/nodes/loaders/NodeMaterialLoader.js +42 -0
- package/examples/jsm/nodes/loaders/NodeObjectLoader.js +70 -0
- package/examples/jsm/{renderers/nodes → nodes}/materials/LineBasicNodeMaterial.js +11 -4
- package/examples/jsm/nodes/materials/Materials.js +65 -0
- package/examples/jsm/{renderers/nodes → nodes}/materials/MeshBasicNodeMaterial.js +13 -4
- package/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +162 -22
- package/examples/jsm/nodes/materials/NodeMaterial.js +128 -113
- package/examples/jsm/{renderers/nodes → nodes}/materials/PointsNodeMaterial.js +13 -4
- package/examples/jsm/nodes/materials/SpriteNodeMaterial.js +84 -16
- package/examples/jsm/nodes/math/CondNode.js +26 -95
- package/examples/jsm/nodes/math/MathNode.js +164 -187
- package/examples/jsm/nodes/math/OperatorNode.js +161 -41
- package/examples/jsm/{renderers/nodes → nodes}/parsers/GLSLNodeFunction.js +2 -2
- package/examples/jsm/{renderers/nodes → nodes}/parsers/GLSLNodeParser.js +0 -0
- package/examples/jsm/{renderers/nodes → nodes}/parsers/WGSLNodeFunction.js +20 -5
- package/examples/jsm/{renderers/nodes → nodes}/parsers/WGSLNodeParser.js +0 -0
- package/examples/jsm/nodes/procedural/CheckerNode.js +16 -57
- package/examples/jsm/nodes/shadernode/ShaderNode.js +262 -0
- package/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js +274 -0
- package/examples/jsm/nodes/shadernode/ShaderNodeElements.js +106 -0
- package/examples/jsm/{renderers/nodes → nodes}/utils/ArrayElementNode.js +3 -3
- package/examples/jsm/{renderers/nodes → nodes}/utils/ConvertNode.js +11 -3
- package/examples/jsm/nodes/utils/JoinNode.js +17 -89
- package/examples/jsm/nodes/utils/MatcapUVNode.js +25 -0
- package/examples/jsm/nodes/utils/MaxMipLevelNode.js +32 -0
- package/examples/jsm/{renderers/nodes → nodes}/utils/OscNode.js +18 -2
- package/examples/jsm/{renderers/nodes → nodes}/utils/SplitNode.js +35 -4
- package/examples/jsm/{renderers/nodes → nodes}/utils/SpriteSheetUVNode.js +3 -3
- package/examples/jsm/nodes/utils/TimerNode.js +30 -65
- package/examples/jsm/objects/Lensflare.js +6 -6
- package/examples/jsm/objects/LightningStorm.js +4 -4
- package/examples/jsm/objects/MarchingCubes.js +5 -9
- package/examples/jsm/objects/Reflector.js +8 -19
- package/examples/jsm/objects/ReflectorForSSRPass.js +2 -14
- package/examples/jsm/objects/Refractor.js +8 -19
- package/examples/jsm/objects/ShadowMesh.js +2 -2
- package/examples/jsm/objects/Sky.js +2 -2
- package/examples/jsm/objects/Water.js +3 -18
- package/examples/jsm/objects/Water2.js +2 -2
- package/examples/jsm/offscreen/jank.js +5 -5
- package/examples/jsm/offscreen/offscreen.js +1 -1
- package/examples/jsm/offscreen/scene.js +11 -11
- package/examples/jsm/postprocessing/AdaptiveToneMappingPass.js +5 -7
- package/examples/jsm/postprocessing/AfterimagePass.js +0 -10
- package/examples/jsm/postprocessing/BloomPass.js +48 -20
- package/examples/jsm/postprocessing/DotScreenPass.js +1 -1
- package/examples/jsm/postprocessing/EffectComposer.js +1 -9
- package/examples/jsm/postprocessing/GlitchPass.js +7 -6
- package/examples/jsm/postprocessing/LUTPass.js +2 -2
- package/examples/jsm/postprocessing/OutlinePass.js +8 -15
- package/examples/jsm/postprocessing/SAOPass.js +2 -9
- package/examples/jsm/postprocessing/SMAAPass.js +2 -11
- package/examples/jsm/postprocessing/SSAARenderPass.js +1 -4
- package/examples/jsm/postprocessing/SSAOPass.js +13 -25
- package/examples/jsm/postprocessing/SSRPass.js +3 -9
- package/examples/jsm/postprocessing/SavePass.js +1 -3
- package/examples/jsm/postprocessing/TAARenderPass.js +4 -4
- package/examples/jsm/postprocessing/UnrealBloomPass.js +3 -8
- package/examples/jsm/renderers/CSS2DRenderer.js +21 -19
- package/examples/jsm/renderers/CSS3DRenderer.js +39 -34
- package/examples/jsm/renderers/Projector.js +101 -128
- package/examples/jsm/renderers/SVGRenderer.js +4 -4
- package/examples/jsm/renderers/webgl/nodes/SlotNode.js +1 -1
- package/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js +127 -23
- package/examples/jsm/renderers/webgl/nodes/WebGLNodes.js +14 -3
- package/examples/jsm/renderers/webgl/nodes/WebGLPhysicalContextNode.js +5 -5
- package/examples/jsm/renderers/webgpu/WebGPUAttributes.js +4 -4
- package/examples/jsm/renderers/webgpu/WebGPUBackground.js +16 -10
- package/examples/jsm/renderers/webgpu/WebGPUBindings.js +8 -7
- package/examples/jsm/renderers/webgpu/WebGPUBuffer.js +43 -0
- package/examples/jsm/renderers/webgpu/WebGPUComputePipelines.js +14 -7
- package/examples/jsm/renderers/webgpu/WebGPUInfo.js +1 -1
- package/examples/jsm/renderers/webgpu/WebGPUObjects.js +0 -6
- package/examples/jsm/renderers/webgpu/WebGPURenderPipeline.js +20 -20
- package/examples/jsm/renderers/webgpu/WebGPURenderPipelines.js +2 -1
- package/examples/jsm/renderers/webgpu/WebGPURenderStates.js +66 -0
- package/examples/jsm/renderers/webgpu/WebGPURenderer.js +49 -28
- package/examples/jsm/renderers/webgpu/WebGPUSampledTexture.js +14 -14
- package/examples/jsm/renderers/webgpu/WebGPUSampler.js +2 -2
- package/examples/jsm/renderers/webgpu/WebGPUStorageBuffer.js +5 -8
- package/examples/jsm/renderers/webgpu/WebGPUTextureUtils.js +23 -20
- package/examples/jsm/renderers/webgpu/WebGPUTextures.js +38 -20
- package/examples/jsm/renderers/webgpu/WebGPUUniform.js +14 -14
- package/examples/jsm/renderers/webgpu/WebGPUUniformBuffer.js +5 -32
- package/examples/jsm/renderers/webgpu/WebGPUUniformsGroup.js +2 -2
- package/examples/jsm/renderers/webgpu/constants.js +3 -2
- package/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js +276 -278
- package/examples/jsm/renderers/webgpu/nodes/WebGPUNodeSampledTexture.js +20 -2
- package/examples/jsm/renderers/webgpu/nodes/WebGPUNodes.js +24 -14
- package/examples/jsm/shaders/BlendShader.js +2 -1
- package/examples/jsm/shaders/CopyShader.js +4 -3
- package/examples/jsm/shaders/DigitalGlitch.js +3 -3
- package/examples/jsm/shaders/FXAAShader.js +219 -1051
- package/examples/jsm/shaders/FreiChenShader.js +1 -1
- package/examples/jsm/shaders/HorizontalBlurShader.js +1 -1
- package/examples/jsm/shaders/HorizontalTiltShiftShader.js +1 -1
- package/examples/jsm/shaders/MMDToonShader.js +0 -1
- package/examples/jsm/shaders/SSAOShader.js +1 -1
- package/examples/jsm/shaders/SSRShader.js +3 -3
- package/examples/jsm/shaders/ToneMapShader.js +1 -1
- package/examples/jsm/utils/BufferGeometryUtils.js +292 -22
- package/examples/jsm/utils/GPUStatsPanel.js +1 -1
- package/examples/jsm/utils/LDrawUtils.js +202 -0
- package/examples/jsm/utils/SceneUtils.js +76 -2
- package/examples/jsm/utils/SkeletonUtils.js +1 -1
- package/examples/jsm/utils/UVsDebug.js +23 -32
- package/examples/jsm/webxr/ARButton.js +14 -4
- package/examples/jsm/webxr/OculusHandPointerModel.js +3 -3
- package/examples/jsm/webxr/Text2D.js +1 -1
- package/examples/jsm/webxr/VRButton.js +39 -1
- package/examples/jsm/webxr/XREstimatedLight.js +2 -0
- package/examples/jsm/webxr/XRHandMeshModel.js +3 -7
- package/examples/jsm/webxr/XRHandModelFactory.js +3 -0
- package/package.json +53 -25
- package/src/Three.Legacy.js +41 -1912
- package/src/Three.js +6 -3
- package/src/animation/AnimationClip.js +1 -1
- package/src/animation/AnimationMixer.js +6 -3
- package/src/animation/AnimationObjectGroup.js +2 -2
- package/src/animation/PropertyBinding.js +8 -18
- package/src/audio/PositionalAudio.js +8 -0
- package/src/cameras/ArrayCamera.js +2 -3
- package/src/cameras/Camera.js +2 -2
- package/src/cameras/CubeCamera.js +8 -1
- package/src/cameras/OrthographicCamera.js +2 -2
- package/src/cameras/PerspectiveCamera.js +2 -2
- package/src/constants.js +8 -18
- package/src/core/BufferAttribute.js +7 -12
- package/src/core/BufferGeometry.js +6 -6
- package/src/core/GLBufferAttribute.js +2 -2
- package/src/core/InstancedBufferAttribute.js +2 -2
- package/src/core/InstancedBufferGeometry.js +2 -2
- package/src/core/InstancedInterleavedBuffer.js +2 -2
- package/src/core/InterleavedBuffer.js +2 -2
- package/src/core/InterleavedBufferAttribute.js +5 -11
- package/src/core/Object3D.js +6 -3
- package/src/core/Raycaster.js +2 -2
- package/src/extras/DataUtils.js +127 -40
- package/src/extras/Earcut.js +2 -2
- package/src/extras/ImageUtils.js +63 -0
- package/src/extras/PMREMGenerator.js +152 -174
- package/src/extras/core/CurvePath.js +3 -3
- package/src/extras/core/ShapePath.js +5 -6
- package/src/extras/curves/ArcCurve.js +2 -2
- package/src/extras/curves/CatmullRomCurve3.js +2 -2
- package/src/extras/curves/CubicBezierCurve.js +2 -2
- package/src/extras/curves/CubicBezierCurve3.js +2 -2
- package/src/extras/curves/EllipseCurve.js +2 -2
- package/src/extras/curves/LineCurve.js +2 -2
- package/src/extras/curves/LineCurve3.js +2 -1
- package/src/extras/curves/QuadraticBezierCurve.js +2 -2
- package/src/extras/curves/QuadraticBezierCurve3.js +2 -2
- package/src/extras/curves/SplineCurve.js +2 -2
- package/src/geometries/CapsuleGeometry.js +33 -0
- package/src/geometries/ExtrudeGeometry.js +2 -0
- package/src/geometries/Geometries.js +1 -0
- package/src/geometries/LatheGeometry.js +1 -1
- package/src/geometries/TorusKnotGeometry.js +2 -2
- package/src/geometries/WireframeGeometry.js +3 -2
- package/src/helpers/BoxHelper.js +2 -2
- package/src/helpers/PointLightHelper.js +1 -1
- package/src/helpers/SkeletonHelper.js +3 -2
- package/src/lights/AmbientLight.js +2 -2
- package/src/lights/AmbientLightProbe.js +2 -2
- package/src/lights/DirectionalLight.js +2 -2
- package/src/lights/DirectionalLightShadow.js +2 -2
- package/src/lights/HemisphereLight.js +4 -4
- package/src/lights/HemisphereLightProbe.js +2 -2
- package/src/lights/Light.js +4 -4
- package/src/lights/LightProbe.js +2 -2
- package/src/lights/PointLight.js +4 -4
- package/src/lights/PointLightShadow.js +2 -2
- package/src/lights/RectAreaLight.js +2 -2
- package/src/lights/SpotLight.js +4 -4
- package/src/lights/SpotLightShadow.js +2 -2
- package/src/loaders/FileLoader.js +23 -4
- package/src/loaders/ImageBitmapLoader.js +2 -2
- package/src/loaders/ImageLoader.js +1 -1
- package/src/loaders/LoaderUtils.js +1 -1
- package/src/loaders/MaterialLoader.js +8 -3
- package/src/loaders/ObjectLoader.js +23 -25
- package/src/materials/LineBasicMaterial.js +6 -13
- package/src/materials/LineDashedMaterial.js +2 -15
- package/src/materials/Material.js +49 -15
- package/src/materials/Materials.js +66 -18
- package/src/materials/MeshBasicMaterial.js +6 -31
- package/src/materials/MeshDepthMaterial.js +2 -22
- package/src/materials/MeshDistanceMaterial.js +2 -22
- package/src/materials/MeshLambertMaterial.js +6 -34
- package/src/materials/MeshMatcapMaterial.js +6 -28
- package/src/materials/MeshNormalMaterial.js +2 -26
- package/src/materials/MeshPhongMaterial.js +6 -48
- package/src/materials/MeshPhysicalMaterial.js +32 -35
- package/src/materials/MeshStandardMaterial.js +6 -54
- package/src/materials/MeshToonMaterial.js +6 -38
- package/src/materials/PointsMaterial.js +6 -15
- package/src/materials/RawShaderMaterial.js +2 -2
- package/src/materials/ShaderMaterial.js +3 -17
- package/src/materials/ShadowMaterial.js +6 -8
- package/src/materials/SpriteMaterial.js +6 -12
- package/src/math/Box2.js +2 -2
- package/src/math/Box3.js +29 -15
- package/src/math/Color.js +85 -36
- package/src/math/ColorManagement.js +74 -0
- package/src/math/Euler.js +16 -14
- package/src/math/Interpolant.js +4 -9
- package/src/math/MathUtils.js +76 -7
- package/src/math/Matrix3.js +2 -2
- package/src/math/Matrix4.js +2 -3
- package/src/math/Plane.js +2 -2
- package/src/math/Quaternion.js +12 -3
- package/src/math/Spherical.js +1 -1
- package/src/math/SphericalHarmonics3.js +2 -2
- package/src/math/Vector2.js +2 -2
- package/src/math/Vector3.js +12 -3
- package/src/math/Vector4.js +2 -2
- package/src/math/interpolants/DiscreteInterpolant.js +1 -1
- package/src/objects/Bone.js +2 -2
- package/src/objects/Group.js +2 -2
- package/src/objects/InstancedMesh.js +4 -4
- package/src/objects/Line.js +76 -107
- package/src/objects/LineLoop.js +2 -2
- package/src/objects/LineSegments.js +15 -23
- package/src/objects/Mesh.js +82 -104
- package/src/objects/Points.js +32 -54
- package/src/objects/SkinnedMesh.js +5 -8
- package/src/objects/Sprite.js +4 -4
- package/src/renderers/WebGL3DRenderTarget.js +22 -0
- package/src/renderers/WebGLArrayRenderTarget.js +22 -0
- package/src/renderers/WebGLCubeRenderTarget.js +7 -16
- package/src/renderers/WebGLMultipleRenderTargets.js +8 -5
- package/src/renderers/WebGLRenderTarget.js +19 -18
- package/src/renderers/WebGLRenderer.js +112 -133
- package/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js +46 -0
- package/src/renderers/shaders/ShaderChunk/common.glsl.js +1 -0
- package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +12 -13
- package/src/renderers/shaders/ShaderChunk/dithering_pars_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js +0 -2
- package/src/renderers/shaders/ShaderChunk/encodings_pars_fragment.glsl.js +0 -4
- package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +0 -2
- package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +3 -19
- package/src/renderers/shaders/ShaderChunk/iridescence_fragment.glsl.js +107 -0
- package/src/renderers/shaders/ShaderChunk/iridescence_pars_fragment.glsl.js +14 -0
- package/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js +1 -7
- package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +25 -0
- package/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js +1 -7
- package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +25 -2
- package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +43 -5
- 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/morphcolor_vertex.glsl.js +24 -0
- package/src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js +7 -7
- package/src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl.js +1 -9
- package/src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl.js +16 -31
- package/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +9 -8
- package/src/renderers/shaders/ShaderChunk.js +6 -0
- package/src/renderers/shaders/ShaderLib/background.glsl.js +8 -2
- package/src/renderers/shaders/ShaderLib/equirect.glsl.js +1 -3
- package/src/renderers/shaders/ShaderLib/linedashed.glsl.js +1 -0
- package/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +3 -2
- package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +1 -0
- package/src/renderers/shaders/ShaderLib/meshmatcap.glsl.js +2 -2
- package/src/renderers/shaders/ShaderLib/meshnormal.glsl.js +6 -0
- package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +1 -0
- package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +10 -0
- package/src/renderers/shaders/ShaderLib/meshtoon.glsl.js +1 -0
- package/src/renderers/shaders/ShaderLib/points.glsl.js +1 -0
- package/src/renderers/shaders/ShaderLib.js +8 -2
- package/src/renderers/shaders/UniformsLib.js +2 -2
- package/src/renderers/webgl/WebGLAttributes.js +6 -6
- package/src/renderers/webgl/WebGLBackground.js +5 -2
- package/src/renderers/webgl/WebGLBindingStates.js +57 -29
- package/src/renderers/webgl/WebGLCubeMaps.js +0 -4
- package/src/renderers/webgl/WebGLCubeUVMaps.js +29 -16
- package/src/renderers/webgl/WebGLGeometries.js +2 -2
- package/src/renderers/webgl/WebGLLights.js +0 -1
- package/src/renderers/webgl/WebGLMaterials.js +72 -187
- package/src/renderers/webgl/WebGLMorphtargets.js +59 -23
- package/src/renderers/webgl/WebGLProgram.js +56 -30
- package/src/renderers/webgl/WebGLPrograms.js +80 -130
- package/src/renderers/webgl/WebGLShaderCache.js +4 -3
- package/src/renderers/webgl/WebGLShadowMap.js +6 -8
- package/src/renderers/webgl/WebGLState.js +83 -2
- package/src/renderers/webgl/WebGLTextures.js +618 -375
- package/src/renderers/webgl/WebGLUniforms.js +79 -80
- package/src/renderers/webgl/WebGLUtils.js +97 -30
- package/src/renderers/webxr/WebXRManager.js +64 -47
- package/src/scenes/Fog.js +2 -2
- package/src/scenes/FogExp2.js +2 -2
- package/src/scenes/Scene.js +2 -2
- package/src/textures/CanvasTexture.js +2 -2
- package/src/textures/CompressedTexture.js +2 -2
- package/src/textures/CubeTexture.js +2 -2
- package/src/textures/{DataTexture3D.js → Data3DTexture.js} +4 -4
- package/src/textures/{DataTexture2DArray.js → DataArrayTexture.js} +4 -4
- package/src/textures/DataTexture.js +2 -5
- package/src/textures/DepthTexture.js +5 -5
- package/src/textures/FramebufferTexture.js +2 -2
- package/src/textures/Source.js +123 -0
- package/src/textures/Texture.js +29 -98
- package/src/textures/VideoTexture.js +2 -4
- package/src/utils.js +15 -1
- package/examples/js/WebGL.js +0 -90
- package/examples/js/csm/Frustum.js +0 -133
- package/examples/js/deprecated/Geometry.js +0 -1656
- package/examples/js/loaders/VRMLoader.js +0 -72
- package/examples/js/objects/ReflectorRTT.js +0 -16
- package/examples/js/postprocessing/SSRrPass.js +0 -494
- package/examples/js/shaders/SSRrShader.js +0 -336
- package/examples/js/utils/RoughnessMipmapper.js +0 -268
- package/examples/jsm/deprecated/Geometry.js +0 -1869
- package/examples/jsm/libs/opentype.module.min.js +0 -119
- package/examples/jsm/loaders/NodeMaterialLoader.js +0 -263
- package/examples/jsm/loaders/VRMLoader.js +0 -78
- package/examples/jsm/nodes/accessors/ColorsNode.js +0 -56
- package/examples/jsm/nodes/accessors/LightNode.js +0 -60
- package/examples/jsm/nodes/accessors/ResolutionNode.js +0 -64
- package/examples/jsm/nodes/accessors/ScreenUVNode.js +0 -64
- package/examples/jsm/nodes/core/NodeLib.js +0 -64
- package/examples/jsm/nodes/core/StructNode.js +0 -106
- package/examples/jsm/nodes/effects/BlurNode.js +0 -171
- package/examples/jsm/nodes/effects/ColorAdjustmentNode.js +0 -140
- package/examples/jsm/nodes/effects/LuminanceNode.js +0 -75
- package/examples/jsm/nodes/inputs/BoolNode.js +0 -51
- package/examples/jsm/nodes/inputs/ColorNode.js +0 -58
- package/examples/jsm/nodes/inputs/CubeTextureNode.js +0 -108
- package/examples/jsm/nodes/inputs/FloatNode.js +0 -51
- package/examples/jsm/nodes/inputs/IntNode.js +0 -51
- package/examples/jsm/nodes/inputs/Matrix3Node.js +0 -63
- package/examples/jsm/nodes/inputs/Matrix4Node.js +0 -63
- package/examples/jsm/nodes/inputs/PropertyNode.js +0 -47
- package/examples/jsm/nodes/inputs/RTTNode.js +0 -157
- package/examples/jsm/nodes/inputs/ReflectorNode.js +0 -90
- package/examples/jsm/nodes/inputs/ScreenNode.js +0 -28
- package/examples/jsm/nodes/inputs/TextureNode.js +0 -116
- package/examples/jsm/nodes/inputs/Vector2Node.js +0 -57
- package/examples/jsm/nodes/inputs/Vector3Node.js +0 -58
- package/examples/jsm/nodes/inputs/Vector4Node.js +0 -59
- package/examples/jsm/nodes/materials/BasicNodeMaterial.js +0 -26
- package/examples/jsm/nodes/materials/PhongNodeMaterial.js +0 -36
- package/examples/jsm/nodes/materials/StandardNodeMaterial.js +0 -40
- package/examples/jsm/nodes/materials/nodes/BasicNode.js +0 -154
- package/examples/jsm/nodes/materials/nodes/MeshStandardNode.js +0 -116
- package/examples/jsm/nodes/materials/nodes/PhongNode.js +0 -409
- package/examples/jsm/nodes/materials/nodes/RawNode.js +0 -62
- package/examples/jsm/nodes/materials/nodes/SpriteNode.js +0 -236
- package/examples/jsm/nodes/materials/nodes/StandardNode.js +0 -609
- package/examples/jsm/nodes/misc/BumpMapNode.js +0 -163
- package/examples/jsm/nodes/misc/NormalMapNode.js +0 -138
- package/examples/jsm/nodes/misc/TextureCubeNode.js +0 -86
- package/examples/jsm/nodes/misc/TextureCubeUVNode.js +0 -280
- package/examples/jsm/nodes/postprocessing/NodePass.js +0 -93
- package/examples/jsm/nodes/postprocessing/NodePostProcessing.js +0 -148
- package/examples/jsm/nodes/procedural/Fractal3DNode.js +0 -104
- package/examples/jsm/nodes/procedural/Noise2DNode.js +0 -149
- package/examples/jsm/nodes/procedural/Noise3DNode.js +0 -141
- package/examples/jsm/nodes/utils/BypassNode.js +0 -85
- package/examples/jsm/nodes/utils/ColorSpaceNode.js +0 -154
- package/examples/jsm/nodes/utils/MaxMIPLevelNode.js +0 -56
- package/examples/jsm/nodes/utils/RemapNode.js +0 -155
- package/examples/jsm/nodes/utils/SpecularMIPLevelNode.js +0 -101
- package/examples/jsm/nodes/utils/SubSlotNode.js +0 -77
- package/examples/jsm/nodes/utils/SwitchNode.js +0 -103
- package/examples/jsm/nodes/utils/UVTransformNode.js +0 -66
- package/examples/jsm/nodes/utils/VelocityNode.js +0 -170
- package/examples/jsm/objects/ReflectorRTT.js +0 -15
- package/examples/jsm/postprocessing/SSRrPass.js +0 -579
- package/examples/jsm/renderers/nodes/Nodes.js +0 -164
- package/examples/jsm/renderers/nodes/ShaderNode.js +0 -346
- package/examples/jsm/renderers/nodes/accessors/CameraNode.js +0 -68
- package/examples/jsm/renderers/nodes/accessors/NormalNode.js +0 -63
- package/examples/jsm/renderers/nodes/accessors/PositionNode.js +0 -67
- package/examples/jsm/renderers/nodes/accessors/ReferenceNode.js +0 -91
- package/examples/jsm/renderers/nodes/accessors/SkinningNode.js +0 -107
- package/examples/jsm/renderers/nodes/accessors/UVNode.js +0 -25
- package/examples/jsm/renderers/nodes/core/ArrayInputNode.js +0 -23
- package/examples/jsm/renderers/nodes/core/AttributeNode.js +0 -54
- package/examples/jsm/renderers/nodes/core/ExpressionNode.js +0 -32
- package/examples/jsm/renderers/nodes/core/FunctionCallNode.js +0 -67
- package/examples/jsm/renderers/nodes/core/FunctionNode.js +0 -87
- package/examples/jsm/renderers/nodes/core/InputNode.js +0 -66
- package/examples/jsm/renderers/nodes/core/Node.js +0 -104
- package/examples/jsm/renderers/nodes/core/NodeBuilder.js +0 -633
- package/examples/jsm/renderers/nodes/core/NodeFrame.js +0 -59
- package/examples/jsm/renderers/nodes/core/NodeUniform.js +0 -28
- package/examples/jsm/renderers/nodes/core/TempNode.js +0 -43
- package/examples/jsm/renderers/nodes/core/VarNode.js +0 -51
- package/examples/jsm/renderers/nodes/display/ColorSpaceNode.js +0 -133
- package/examples/jsm/renderers/nodes/display/NormalMapNode.js +0 -87
- package/examples/jsm/renderers/nodes/functions/BSDFs.js +0 -122
- package/examples/jsm/renderers/nodes/functions/PhysicalMaterialFunctions.js +0 -27
- package/examples/jsm/renderers/nodes/inputs/BufferNode.js +0 -25
- package/examples/jsm/renderers/nodes/inputs/ColorNode.js +0 -18
- package/examples/jsm/renderers/nodes/inputs/FloatNode.js +0 -17
- package/examples/jsm/renderers/nodes/inputs/IntNode.js +0 -17
- package/examples/jsm/renderers/nodes/inputs/Matrix3Node.js +0 -18
- package/examples/jsm/renderers/nodes/inputs/Matrix4Node.js +0 -18
- package/examples/jsm/renderers/nodes/inputs/TextureNode.js +0 -79
- package/examples/jsm/renderers/nodes/inputs/Vector2Node.js +0 -18
- package/examples/jsm/renderers/nodes/inputs/Vector3Node.js +0 -18
- package/examples/jsm/renderers/nodes/inputs/Vector4Node.js +0 -18
- package/examples/jsm/renderers/nodes/lights/LightContextNode.js +0 -59
- package/examples/jsm/renderers/nodes/lights/LightNode.js +0 -79
- package/examples/jsm/renderers/nodes/lights/LightsNode.js +0 -44
- package/examples/jsm/renderers/nodes/materials/Materials.js +0 -11
- package/examples/jsm/renderers/nodes/materials/MeshStandardNodeMaterial.js +0 -63
- package/examples/jsm/renderers/nodes/math/CondNode.js +0 -60
- package/examples/jsm/renderers/nodes/math/MathNode.js +0 -241
- package/examples/jsm/renderers/nodes/math/OperatorNode.js +0 -174
- package/examples/jsm/renderers/nodes/procedural/CheckerNode.js +0 -36
- package/examples/jsm/renderers/nodes/utils/JoinNode.js +0 -42
- package/examples/jsm/renderers/nodes/utils/TimerNode.js +0 -47
- package/examples/jsm/renderers/webgpu/nodes/WebGPUNodeUniformsGroup.js +0 -20
- package/examples/jsm/shaders/SSRrShader.js +0 -307
- package/examples/jsm/utils/RoughnessMipmapper.js +0 -288
- package/src/renderers/WebGLMultisampleRenderTarget.js +0 -33
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
const FILE_LOCATION_TRY_RELATIVE = 4;
|
|
18
18
|
const FILE_LOCATION_TRY_ABSOLUTE = 5;
|
|
19
19
|
const FILE_LOCATION_NOT_FOUND = 6;
|
|
20
|
+
const MAIN_COLOUR_CODE = '16';
|
|
21
|
+
const MAIN_EDGE_COLOUR_CODE = '24';
|
|
20
22
|
|
|
21
23
|
const _tempVec0 = new THREE.Vector3();
|
|
22
24
|
|
|
@@ -142,16 +144,56 @@
|
|
|
142
144
|
|
|
143
145
|
}
|
|
144
146
|
|
|
145
|
-
|
|
147
|
+
class ConditionalLineSegments extends THREE.LineSegments {
|
|
148
|
+
|
|
149
|
+
constructor( geometry, material ) {
|
|
150
|
+
|
|
151
|
+
super( geometry, material );
|
|
152
|
+
this.isConditionalLine = true;
|
|
153
|
+
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function generateFaceNormals( faces ) {
|
|
159
|
+
|
|
160
|
+
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
161
|
+
|
|
162
|
+
const face = faces[ i ];
|
|
163
|
+
const vertices = face.vertices;
|
|
164
|
+
const v0 = vertices[ 0 ];
|
|
165
|
+
const v1 = vertices[ 1 ];
|
|
166
|
+
const v2 = vertices[ 2 ];
|
|
167
|
+
|
|
168
|
+
_tempVec0.subVectors( v1, v0 );
|
|
169
|
+
|
|
170
|
+
_tempVec1.subVectors( v2, v1 );
|
|
171
|
+
|
|
172
|
+
face.faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize();
|
|
173
|
+
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const _ray = new THREE.Ray();
|
|
179
|
+
|
|
180
|
+
function smoothNormals( faces, lineSegments, checkSubSegments = false ) {
|
|
181
|
+
|
|
182
|
+
// NOTE: 1e2 is pretty coarse but was chosen to quantize the resulting value because
|
|
183
|
+
// it allows edges to be smoothed as expected (see minifig arms).
|
|
184
|
+
// --
|
|
185
|
+
// And the vector values are initialize multiplied by 1 + 1e-10 to account for floating
|
|
186
|
+
// point errors on vertices along quantization boundaries. Ie after matrix multiplication
|
|
187
|
+
// vertices that should be merged might be set to "1.7" and "1.6999..." meaning they won't
|
|
188
|
+
// get merged. This added epsilon attempts to push these error values to the same quantized
|
|
189
|
+
// value for the sake of hashing. See "AT-ST mini" dishes. See mrdoob/three#23169.
|
|
190
|
+
const hashMultiplier = ( 1 + 1e-10 ) * 1e2;
|
|
146
191
|
|
|
147
192
|
function hashVertex( v ) {
|
|
148
193
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const x = ~ ~ ( v.x * 1e2 );
|
|
153
|
-
const y = ~ ~ ( v.y * 1e2 );
|
|
154
|
-
const z = ~ ~ ( v.z * 1e2 );
|
|
194
|
+
const x = ~ ~ ( v.x * hashMultiplier );
|
|
195
|
+
const y = ~ ~ ( v.y * hashMultiplier );
|
|
196
|
+
const z = ~ ~ ( v.z * hashMultiplier );
|
|
155
197
|
return `${x},${y},${z}`;
|
|
156
198
|
|
|
157
199
|
}
|
|
@@ -160,9 +202,27 @@
|
|
|
160
202
|
|
|
161
203
|
return `${hashVertex( v0 )}_${hashVertex( v1 )}`;
|
|
162
204
|
|
|
205
|
+
} // converts the two vertices to a ray with a normalized direction and origin of 0, 0, 0 projected
|
|
206
|
+
// onto the original line.
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
function toNormalizedRay( v0, v1, targetRay ) {
|
|
210
|
+
|
|
211
|
+
targetRay.direction.subVectors( v1, v0 ).normalize();
|
|
212
|
+
const scalar = v0.dot( targetRay.direction );
|
|
213
|
+
targetRay.origin.copy( v0 ).addScaledVector( targetRay.direction, - scalar );
|
|
214
|
+
return targetRay;
|
|
215
|
+
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function hashRay( ray ) {
|
|
219
|
+
|
|
220
|
+
return hashEdge( ray.origin, ray.direction );
|
|
221
|
+
|
|
163
222
|
}
|
|
164
223
|
|
|
165
224
|
const hardEdges = new Set();
|
|
225
|
+
const hardEdgeRays = new Map();
|
|
166
226
|
const halfEdgeList = {};
|
|
167
227
|
const normals = []; // Save the list of hard edges by hash
|
|
168
228
|
|
|
@@ -173,7 +233,43 @@
|
|
|
173
233
|
const v0 = vertices[ 0 ];
|
|
174
234
|
const v1 = vertices[ 1 ];
|
|
175
235
|
hardEdges.add( hashEdge( v0, v1 ) );
|
|
176
|
-
hardEdges.add( hashEdge( v1, v0 ) );
|
|
236
|
+
hardEdges.add( hashEdge( v1, v0 ) ); // only generate the hard edge ray map if we're checking subsegments because it's more expensive to check
|
|
237
|
+
// and requires more memory.
|
|
238
|
+
|
|
239
|
+
if ( checkSubSegments ) {
|
|
240
|
+
|
|
241
|
+
// add both ray directions to the map
|
|
242
|
+
const ray = toNormalizedRay( v0, v1, new THREE.Ray() );
|
|
243
|
+
const rh1 = hashRay( ray );
|
|
244
|
+
|
|
245
|
+
if ( ! hardEdgeRays.has( rh1 ) ) {
|
|
246
|
+
|
|
247
|
+
toNormalizedRay( v1, v0, ray );
|
|
248
|
+
const rh2 = hashRay( ray );
|
|
249
|
+
const info = {
|
|
250
|
+
ray,
|
|
251
|
+
distances: []
|
|
252
|
+
};
|
|
253
|
+
hardEdgeRays.set( rh1, info );
|
|
254
|
+
hardEdgeRays.set( rh2, info );
|
|
255
|
+
|
|
256
|
+
} // store both segments ends in min, max order in the distances array to check if a face edge is a
|
|
257
|
+
// subsegment later.
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
const info = hardEdgeRays.get( rh1 );
|
|
261
|
+
let d0 = info.ray.direction.dot( v0 );
|
|
262
|
+
let d1 = info.ray.direction.dot( v1 );
|
|
263
|
+
|
|
264
|
+
if ( d0 > d1 ) {
|
|
265
|
+
|
|
266
|
+
[ d0, d1 ] = [ d1, d0 ];
|
|
267
|
+
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
info.distances.push( d0, d1 );
|
|
271
|
+
|
|
272
|
+
}
|
|
177
273
|
|
|
178
274
|
} // track the half edges associated with each triangle
|
|
179
275
|
|
|
@@ -192,7 +288,58 @@
|
|
|
192
288
|
const v1 = vertices[ next ];
|
|
193
289
|
const hash = hashEdge( v0, v1 ); // don't add the triangle if the edge is supposed to be hard
|
|
194
290
|
|
|
195
|
-
if ( hardEdges.has( hash ) )
|
|
291
|
+
if ( hardEdges.has( hash ) ) {
|
|
292
|
+
|
|
293
|
+
continue;
|
|
294
|
+
|
|
295
|
+
} // if checking subsegments then check to see if this edge lies on a hard edge ray and whether its within any ray bounds
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
if ( checkSubSegments ) {
|
|
299
|
+
|
|
300
|
+
toNormalizedRay( v0, v1, _ray );
|
|
301
|
+
const rayHash = hashRay( _ray );
|
|
302
|
+
|
|
303
|
+
if ( hardEdgeRays.has( rayHash ) ) {
|
|
304
|
+
|
|
305
|
+
const info = hardEdgeRays.get( rayHash );
|
|
306
|
+
const {
|
|
307
|
+
ray,
|
|
308
|
+
distances
|
|
309
|
+
} = info;
|
|
310
|
+
let d0 = ray.direction.dot( v0 );
|
|
311
|
+
let d1 = ray.direction.dot( v1 );
|
|
312
|
+
|
|
313
|
+
if ( d0 > d1 ) {
|
|
314
|
+
|
|
315
|
+
[ d0, d1 ] = [ d1, d0 ];
|
|
316
|
+
|
|
317
|
+
} // return early if the face edge is found to be a subsegment of a line edge meaning the edge will have "hard" normals
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
let found = false;
|
|
321
|
+
|
|
322
|
+
for ( let i = 0, l = distances.length; i < l; i += 2 ) {
|
|
323
|
+
|
|
324
|
+
if ( d0 >= distances[ i ] && d1 <= distances[ i + 1 ] ) {
|
|
325
|
+
|
|
326
|
+
found = true;
|
|
327
|
+
break;
|
|
328
|
+
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if ( found ) {
|
|
334
|
+
|
|
335
|
+
continue;
|
|
336
|
+
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
}
|
|
342
|
+
|
|
196
343
|
const info = {
|
|
197
344
|
index: index,
|
|
198
345
|
tri: tri
|
|
@@ -363,13 +510,7 @@
|
|
|
363
510
|
|
|
364
511
|
function isPartType( type ) {
|
|
365
512
|
|
|
366
|
-
return type === 'Part';
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
function isModelType( type ) {
|
|
371
|
-
|
|
372
|
-
return type === 'Model' || type === 'Unofficial_Model';
|
|
513
|
+
return type === 'Part' || type === 'Unofficial_Part';
|
|
373
514
|
|
|
374
515
|
}
|
|
375
516
|
|
|
@@ -433,6 +574,12 @@
|
|
|
433
574
|
|
|
434
575
|
}
|
|
435
576
|
|
|
577
|
+
getVector() {
|
|
578
|
+
|
|
579
|
+
return new THREE.Vector3( parseFloat( this.getToken() ), parseFloat( this.getToken() ), parseFloat( this.getToken() ) );
|
|
580
|
+
|
|
581
|
+
}
|
|
582
|
+
|
|
436
583
|
getRemainingString() {
|
|
437
584
|
|
|
438
585
|
return this.line.substring( this.currentCharIndex, this.lineLength );
|
|
@@ -457,1469 +604,1702 @@
|
|
|
457
604
|
|
|
458
605
|
}
|
|
459
606
|
|
|
460
|
-
}
|
|
607
|
+
} // Fetches and parses an intermediate representation of LDraw parts files.
|
|
608
|
+
|
|
461
609
|
|
|
462
|
-
class
|
|
610
|
+
class LDrawParsedCache {
|
|
463
611
|
|
|
464
612
|
constructor( loader ) {
|
|
465
613
|
|
|
466
|
-
this.cache = {};
|
|
467
614
|
this.loader = loader;
|
|
615
|
+
this._cache = {};
|
|
468
616
|
|
|
469
617
|
}
|
|
470
618
|
|
|
471
|
-
|
|
619
|
+
cloneResult( original ) {
|
|
472
620
|
|
|
473
|
-
|
|
621
|
+
const result = {}; // vertices are transformed and normals computed before being converted to geometry
|
|
622
|
+
// so these pieces must be cloned.
|
|
474
623
|
|
|
475
|
-
|
|
624
|
+
result.faces = original.faces.map( face => {
|
|
476
625
|
|
|
477
|
-
|
|
626
|
+
return {
|
|
627
|
+
colorCode: face.colorCode,
|
|
628
|
+
material: face.material,
|
|
629
|
+
vertices: face.vertices.map( v => v.clone() ),
|
|
630
|
+
normals: face.normals.map( () => null ),
|
|
631
|
+
faceNormal: null
|
|
632
|
+
};
|
|
478
633
|
|
|
479
|
-
|
|
634
|
+
} );
|
|
635
|
+
result.conditionalSegments = original.conditionalSegments.map( face => {
|
|
480
636
|
|
|
481
|
-
|
|
637
|
+
return {
|
|
638
|
+
colorCode: face.colorCode,
|
|
639
|
+
material: face.material,
|
|
640
|
+
vertices: face.vertices.map( v => v.clone() ),
|
|
641
|
+
controlPoints: face.controlPoints.map( v => v.clone() )
|
|
642
|
+
};
|
|
482
643
|
|
|
483
|
-
|
|
644
|
+
} );
|
|
645
|
+
result.lineSegments = original.lineSegments.map( face => {
|
|
484
646
|
|
|
485
|
-
|
|
647
|
+
return {
|
|
648
|
+
colorCode: face.colorCode,
|
|
649
|
+
material: face.material,
|
|
650
|
+
vertices: face.vertices.map( v => v.clone() )
|
|
651
|
+
};
|
|
486
652
|
|
|
487
|
-
|
|
653
|
+
} ); // none if this is subsequently modified
|
|
488
654
|
|
|
489
|
-
|
|
490
|
-
|
|
655
|
+
result.type = original.type;
|
|
656
|
+
result.category = original.category;
|
|
657
|
+
result.keywords = original.keywords;
|
|
658
|
+
result.subobjects = original.subobjects;
|
|
659
|
+
result.totalFaces = original.totalFaces;
|
|
660
|
+
result.startingConstructionStep = original.startingConstructionStep;
|
|
661
|
+
result.materials = original.materials;
|
|
662
|
+
result.group = null;
|
|
663
|
+
return result;
|
|
491
664
|
|
|
492
|
-
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
async fetchData( fileName ) {
|
|
493
668
|
|
|
494
|
-
|
|
669
|
+
let triedLowerCase = false;
|
|
670
|
+
let locationState = FILE_LOCATION_AS_IS;
|
|
495
671
|
|
|
496
|
-
|
|
672
|
+
while ( locationState !== FILE_LOCATION_NOT_FOUND ) {
|
|
497
673
|
|
|
498
|
-
|
|
499
|
-
locationState = locationState + 1;
|
|
500
|
-
break;
|
|
674
|
+
let subobjectURL = fileName;
|
|
501
675
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
676
|
+
switch ( locationState ) {
|
|
677
|
+
|
|
678
|
+
case FILE_LOCATION_AS_IS:
|
|
679
|
+
locationState = locationState + 1;
|
|
680
|
+
break;
|
|
506
681
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
682
|
+
case FILE_LOCATION_TRY_PARTS:
|
|
683
|
+
subobjectURL = 'parts/' + subobjectURL;
|
|
684
|
+
locationState = locationState + 1;
|
|
685
|
+
break;
|
|
511
686
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
687
|
+
case FILE_LOCATION_TRY_P:
|
|
688
|
+
subobjectURL = 'p/' + subobjectURL;
|
|
689
|
+
locationState = locationState + 1;
|
|
690
|
+
break;
|
|
516
691
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
692
|
+
case FILE_LOCATION_TRY_MODELS:
|
|
693
|
+
subobjectURL = 'models/' + subobjectURL;
|
|
694
|
+
locationState = locationState + 1;
|
|
695
|
+
break;
|
|
521
696
|
|
|
522
|
-
|
|
523
|
-
|
|
697
|
+
case FILE_LOCATION_TRY_RELATIVE:
|
|
698
|
+
subobjectURL = fileName.substring( 0, fileName.lastIndexOf( '/' ) + 1 ) + subobjectURL;
|
|
699
|
+
locationState = locationState + 1;
|
|
700
|
+
break;
|
|
524
701
|
|
|
525
|
-
|
|
526
|
-
|
|
702
|
+
case FILE_LOCATION_TRY_ABSOLUTE:
|
|
703
|
+
if ( triedLowerCase ) {
|
|
527
704
|
|
|
528
|
-
|
|
705
|
+
// Try absolute path
|
|
706
|
+
locationState = FILE_LOCATION_NOT_FOUND;
|
|
529
707
|
|
|
530
|
-
|
|
531
|
-
fileName = fileName.toLowerCase();
|
|
532
|
-
subobjectURL = fileName;
|
|
533
|
-
triedLowerCase = true;
|
|
534
|
-
locationState = FILE_LOCATION_AS_IS;
|
|
708
|
+
} else {
|
|
535
709
|
|
|
536
|
-
|
|
710
|
+
// Next attempt is lower case
|
|
711
|
+
fileName = fileName.toLowerCase();
|
|
712
|
+
subobjectURL = fileName;
|
|
713
|
+
triedLowerCase = true;
|
|
714
|
+
locationState = FILE_LOCATION_AS_IS;
|
|
537
715
|
|
|
538
|
-
|
|
716
|
+
}
|
|
539
717
|
|
|
540
|
-
|
|
718
|
+
break;
|
|
541
719
|
|
|
542
|
-
|
|
543
|
-
const fileLoader = new THREE.FileLoader( loader.manager );
|
|
544
|
-
fileLoader.setPath( loader.partsLibraryPath );
|
|
545
|
-
fileLoader.setRequestHeader( loader.requestHeader );
|
|
546
|
-
fileLoader.setWithCredentials( loader.withCredentials );
|
|
720
|
+
}
|
|
547
721
|
|
|
548
|
-
|
|
722
|
+
const loader = this.loader;
|
|
723
|
+
const fileLoader = new THREE.FileLoader( loader.manager );
|
|
724
|
+
fileLoader.setPath( loader.partsLibraryPath );
|
|
725
|
+
fileLoader.setRequestHeader( loader.requestHeader );
|
|
726
|
+
fileLoader.setWithCredentials( loader.withCredentials );
|
|
549
727
|
|
|
550
|
-
|
|
551
|
-
this.setData( fileName, text );
|
|
552
|
-
resolve( text );
|
|
553
|
-
return;
|
|
728
|
+
try {
|
|
554
729
|
|
|
555
|
-
|
|
730
|
+
const text = await fileLoader.loadAsync( subobjectURL );
|
|
731
|
+
return text;
|
|
556
732
|
|
|
557
|
-
|
|
733
|
+
} catch {
|
|
558
734
|
|
|
559
|
-
|
|
735
|
+
continue;
|
|
560
736
|
|
|
561
737
|
}
|
|
562
738
|
|
|
563
|
-
|
|
739
|
+
}
|
|
564
740
|
|
|
565
|
-
|
|
566
|
-
return this.cache[ fileName ];
|
|
741
|
+
throw new Error( 'LDrawLoader: Subobject "' + fileName + '" could not be loaded.' );
|
|
567
742
|
|
|
568
743
|
}
|
|
569
744
|
|
|
570
|
-
|
|
745
|
+
parse( text, fileName = null ) {
|
|
571
746
|
|
|
572
|
-
|
|
747
|
+
const loader = this.loader; // final results
|
|
573
748
|
|
|
574
|
-
|
|
749
|
+
const faces = [];
|
|
750
|
+
const lineSegments = [];
|
|
751
|
+
const conditionalSegments = [];
|
|
752
|
+
const subobjects = [];
|
|
753
|
+
const materials = {};
|
|
575
754
|
|
|
576
|
-
|
|
755
|
+
const getLocalMaterial = colorCode => {
|
|
577
756
|
|
|
578
|
-
|
|
757
|
+
return materials[ colorCode ] || null;
|
|
579
758
|
|
|
580
|
-
|
|
759
|
+
};
|
|
581
760
|
|
|
582
|
-
|
|
761
|
+
let type = 'Model';
|
|
762
|
+
let category = null;
|
|
763
|
+
let keywords = null;
|
|
764
|
+
let totalFaces = 0; // split into lines
|
|
583
765
|
|
|
584
|
-
|
|
766
|
+
if ( text.indexOf( '\r\n' ) !== - 1 ) {
|
|
585
767
|
|
|
586
|
-
|
|
768
|
+
// This is faster than String.split with regex that splits on both
|
|
769
|
+
text = text.replace( /\r\n/g, '\n' );
|
|
587
770
|
|
|
588
|
-
|
|
771
|
+
}
|
|
589
772
|
|
|
590
|
-
|
|
773
|
+
const lines = text.split( '\n' );
|
|
774
|
+
const numLines = lines.length;
|
|
775
|
+
let parsingEmbeddedFiles = false;
|
|
776
|
+
let currentEmbeddedFileName = null;
|
|
777
|
+
let currentEmbeddedText = null;
|
|
778
|
+
let bfcCertified = false;
|
|
779
|
+
let bfcCCW = true;
|
|
780
|
+
let bfcInverted = false;
|
|
781
|
+
let bfcCull = true;
|
|
782
|
+
let startingConstructionStep = false; // Parse all line commands
|
|
591
783
|
|
|
592
|
-
|
|
593
|
-
// With per face / segment material, implemented with mesh groups and materials array
|
|
594
|
-
// Sort the faces or line segments by colour code to make later the mesh groups
|
|
595
|
-
elements.sort( sortByMaterial );
|
|
784
|
+
for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) {
|
|
596
785
|
|
|
597
|
-
|
|
786
|
+
const line = lines[ lineIndex ];
|
|
787
|
+
if ( line.length === 0 ) continue;
|
|
598
788
|
|
|
599
|
-
|
|
789
|
+
if ( parsingEmbeddedFiles ) {
|
|
600
790
|
|
|
601
|
-
|
|
791
|
+
if ( line.startsWith( '0 FILE ' ) ) {
|
|
602
792
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const materials = [];
|
|
606
|
-
const quadArray = new Array( 6 );
|
|
607
|
-
const bufferGeometry = new THREE.BufferGeometry();
|
|
608
|
-
let prevMaterial = null;
|
|
609
|
-
let index0 = 0;
|
|
610
|
-
let numGroupVerts = 0;
|
|
611
|
-
let offset = 0;
|
|
793
|
+
// Save previous embedded file in the cache
|
|
794
|
+
this.setData( currentEmbeddedFileName, currentEmbeddedText ); // New embedded text file
|
|
612
795
|
|
|
613
|
-
|
|
796
|
+
currentEmbeddedFileName = line.substring( 7 );
|
|
797
|
+
currentEmbeddedText = '';
|
|
614
798
|
|
|
615
|
-
|
|
616
|
-
let vertices = elem.vertices;
|
|
799
|
+
} else {
|
|
617
800
|
|
|
618
|
-
|
|
801
|
+
currentEmbeddedText += line + '\n';
|
|
619
802
|
|
|
620
|
-
|
|
621
|
-
quadArray[ 1 ] = vertices[ 1 ];
|
|
622
|
-
quadArray[ 2 ] = vertices[ 2 ];
|
|
623
|
-
quadArray[ 3 ] = vertices[ 0 ];
|
|
624
|
-
quadArray[ 4 ] = vertices[ 2 ];
|
|
625
|
-
quadArray[ 5 ] = vertices[ 3 ];
|
|
626
|
-
vertices = quadArray;
|
|
803
|
+
}
|
|
627
804
|
|
|
628
|
-
|
|
805
|
+
continue;
|
|
629
806
|
|
|
630
|
-
|
|
807
|
+
}
|
|
631
808
|
|
|
632
|
-
const
|
|
633
|
-
|
|
634
|
-
positions[ index + 0 ] = v.x;
|
|
635
|
-
positions[ index + 1 ] = v.y;
|
|
636
|
-
positions[ index + 2 ] = v.z;
|
|
809
|
+
const lp = new LineParser( line, lineIndex + 1 );
|
|
810
|
+
lp.seekNonSpace();
|
|
637
811
|
|
|
638
|
-
|
|
812
|
+
if ( lp.isAtTheEnd() ) {
|
|
639
813
|
|
|
640
|
-
|
|
814
|
+
// Empty line
|
|
815
|
+
continue;
|
|
641
816
|
|
|
642
|
-
|
|
817
|
+
} // Parse the line type
|
|
643
818
|
|
|
644
|
-
if ( elemNormals.length === 4 ) {
|
|
645
819
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
820
|
+
const lineType = lp.getToken();
|
|
821
|
+
let material;
|
|
822
|
+
let colorCode;
|
|
823
|
+
let segment;
|
|
824
|
+
let ccw;
|
|
825
|
+
let doubleSided;
|
|
826
|
+
let v0, v1, v2, v3, c0, c1;
|
|
653
827
|
|
|
654
|
-
|
|
828
|
+
switch ( lineType ) {
|
|
655
829
|
|
|
656
|
-
|
|
830
|
+
// Line type 0: Comment or META
|
|
831
|
+
case '0':
|
|
832
|
+
// Parse meta directive
|
|
833
|
+
const meta = lp.getToken();
|
|
657
834
|
|
|
658
|
-
|
|
835
|
+
if ( meta ) {
|
|
659
836
|
|
|
660
|
-
|
|
837
|
+
switch ( meta ) {
|
|
661
838
|
|
|
662
|
-
|
|
839
|
+
case '!LDRAW_ORG':
|
|
840
|
+
type = lp.getToken();
|
|
841
|
+
break;
|
|
663
842
|
|
|
664
|
-
|
|
843
|
+
case '!COLOUR':
|
|
844
|
+
material = loader.parseColorMetaDirective( lp );
|
|
665
845
|
|
|
666
|
-
|
|
667
|
-
normals[ index + 0 ] = n.x;
|
|
668
|
-
normals[ index + 1 ] = n.y;
|
|
669
|
-
normals[ index + 2 ] = n.z;
|
|
846
|
+
if ( material ) {
|
|
670
847
|
|
|
671
|
-
|
|
848
|
+
materials[ material.userData.code ] = material;
|
|
672
849
|
|
|
673
|
-
|
|
850
|
+
} else {
|
|
674
851
|
|
|
675
|
-
|
|
852
|
+
console.warn( 'LDrawLoader: Error parsing material' + lp.getLineNumberString() );
|
|
676
853
|
|
|
677
|
-
|
|
854
|
+
}
|
|
678
855
|
|
|
679
|
-
|
|
856
|
+
break;
|
|
680
857
|
|
|
681
|
-
|
|
858
|
+
case '!CATEGORY':
|
|
859
|
+
category = lp.getToken();
|
|
860
|
+
break;
|
|
682
861
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
index0 = offset / 3;
|
|
686
|
-
numGroupVerts = vertices.length;
|
|
862
|
+
case '!KEYWORDS':
|
|
863
|
+
const newKeywords = lp.getRemainingString().split( ',' );
|
|
687
864
|
|
|
688
|
-
|
|
865
|
+
if ( newKeywords.length > 0 ) {
|
|
689
866
|
|
|
690
|
-
|
|
867
|
+
if ( ! keywords ) {
|
|
691
868
|
|
|
692
|
-
|
|
869
|
+
keywords = [];
|
|
693
870
|
|
|
694
|
-
|
|
871
|
+
}
|
|
695
872
|
|
|
696
|
-
|
|
873
|
+
newKeywords.forEach( function ( keyword ) {
|
|
697
874
|
|
|
698
|
-
|
|
875
|
+
keywords.push( keyword.trim() );
|
|
699
876
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
}
|
|
877
|
+
} );
|
|
703
878
|
|
|
704
|
-
|
|
879
|
+
}
|
|
705
880
|
|
|
706
|
-
|
|
881
|
+
break;
|
|
707
882
|
|
|
708
|
-
|
|
883
|
+
case 'FILE':
|
|
884
|
+
if ( lineIndex > 0 ) {
|
|
709
885
|
|
|
710
|
-
|
|
886
|
+
// Start embedded text files parsing
|
|
887
|
+
parsingEmbeddedFiles = true;
|
|
888
|
+
currentEmbeddedFileName = lp.getRemainingString();
|
|
889
|
+
currentEmbeddedText = '';
|
|
890
|
+
bfcCertified = false;
|
|
891
|
+
bfcCCW = true;
|
|
711
892
|
|
|
712
|
-
|
|
893
|
+
}
|
|
713
894
|
|
|
714
|
-
|
|
895
|
+
break;
|
|
715
896
|
|
|
716
|
-
|
|
897
|
+
case 'BFC':
|
|
898
|
+
// Changes to the backface culling state
|
|
899
|
+
while ( ! lp.isAtTheEnd() ) {
|
|
717
900
|
|
|
718
|
-
|
|
901
|
+
const token = lp.getToken();
|
|
719
902
|
|
|
720
|
-
|
|
903
|
+
switch ( token ) {
|
|
721
904
|
|
|
722
|
-
|
|
905
|
+
case 'CERTIFY':
|
|
906
|
+
case 'NOCERTIFY':
|
|
907
|
+
bfcCertified = token === 'CERTIFY';
|
|
908
|
+
bfcCCW = true;
|
|
909
|
+
break;
|
|
723
910
|
|
|
724
|
-
|
|
911
|
+
case 'CW':
|
|
912
|
+
case 'CCW':
|
|
913
|
+
bfcCCW = token === 'CCW';
|
|
914
|
+
break;
|
|
725
915
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
const directionArray = new Float32Array( elements.length * 3 * 2 );
|
|
916
|
+
case 'INVERTNEXT':
|
|
917
|
+
bfcInverted = true;
|
|
918
|
+
break;
|
|
730
919
|
|
|
731
|
-
|
|
920
|
+
case 'CLIP':
|
|
921
|
+
case 'NOCLIP':
|
|
922
|
+
bfcCull = token === 'CLIP';
|
|
923
|
+
break;
|
|
732
924
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
const c0 = controlPoints[ 0 ];
|
|
737
|
-
const c1 = controlPoints[ 1 ];
|
|
738
|
-
const v0 = vertices[ 0 ];
|
|
739
|
-
const v1 = vertices[ 1 ];
|
|
740
|
-
const index = i * 3 * 2;
|
|
741
|
-
controlArray0[ index + 0 ] = c0.x;
|
|
742
|
-
controlArray0[ index + 1 ] = c0.y;
|
|
743
|
-
controlArray0[ index + 2 ] = c0.z;
|
|
744
|
-
controlArray0[ index + 3 ] = c0.x;
|
|
745
|
-
controlArray0[ index + 4 ] = c0.y;
|
|
746
|
-
controlArray0[ index + 5 ] = c0.z;
|
|
747
|
-
controlArray1[ index + 0 ] = c1.x;
|
|
748
|
-
controlArray1[ index + 1 ] = c1.y;
|
|
749
|
-
controlArray1[ index + 2 ] = c1.z;
|
|
750
|
-
controlArray1[ index + 3 ] = c1.x;
|
|
751
|
-
controlArray1[ index + 4 ] = c1.y;
|
|
752
|
-
controlArray1[ index + 5 ] = c1.z;
|
|
753
|
-
directionArray[ index + 0 ] = v1.x - v0.x;
|
|
754
|
-
directionArray[ index + 1 ] = v1.y - v0.y;
|
|
755
|
-
directionArray[ index + 2 ] = v1.z - v0.z;
|
|
756
|
-
directionArray[ index + 3 ] = v1.x - v0.x;
|
|
757
|
-
directionArray[ index + 4 ] = v1.y - v0.y;
|
|
758
|
-
directionArray[ index + 5 ] = v1.z - v0.z;
|
|
925
|
+
default:
|
|
926
|
+
console.warn( 'THREE.LDrawLoader: BFC directive "' + token + '" is unknown.' );
|
|
927
|
+
break;
|
|
759
928
|
|
|
760
|
-
|
|
929
|
+
}
|
|
761
930
|
|
|
762
|
-
|
|
763
|
-
bufferGeometry.setAttribute( 'control1', new THREE.BufferAttribute( controlArray1, 3, false ) );
|
|
764
|
-
bufferGeometry.setAttribute( 'direction', new THREE.BufferAttribute( directionArray, 3, false ) );
|
|
931
|
+
}
|
|
765
932
|
|
|
766
|
-
|
|
933
|
+
break;
|
|
767
934
|
|
|
768
|
-
|
|
935
|
+
case 'STEP':
|
|
936
|
+
startingConstructionStep = true;
|
|
937
|
+
break;
|
|
769
938
|
|
|
770
|
-
|
|
939
|
+
default:
|
|
940
|
+
// Other meta directives are not implemented
|
|
941
|
+
break;
|
|
771
942
|
|
|
943
|
+
}
|
|
772
944
|
|
|
773
|
-
|
|
945
|
+
}
|
|
774
946
|
|
|
775
|
-
|
|
947
|
+
break;
|
|
948
|
+
// Line type 1: Sub-object file
|
|
776
949
|
|
|
777
|
-
|
|
950
|
+
case '1':
|
|
951
|
+
colorCode = lp.getToken();
|
|
952
|
+
material = getLocalMaterial( colorCode );
|
|
953
|
+
const posX = parseFloat( lp.getToken() );
|
|
954
|
+
const posY = parseFloat( lp.getToken() );
|
|
955
|
+
const posZ = parseFloat( lp.getToken() );
|
|
956
|
+
const m0 = parseFloat( lp.getToken() );
|
|
957
|
+
const m1 = parseFloat( lp.getToken() );
|
|
958
|
+
const m2 = parseFloat( lp.getToken() );
|
|
959
|
+
const m3 = parseFloat( lp.getToken() );
|
|
960
|
+
const m4 = parseFloat( lp.getToken() );
|
|
961
|
+
const m5 = parseFloat( lp.getToken() );
|
|
962
|
+
const m6 = parseFloat( lp.getToken() );
|
|
963
|
+
const m7 = parseFloat( lp.getToken() );
|
|
964
|
+
const m8 = parseFloat( lp.getToken() );
|
|
965
|
+
const matrix = new THREE.Matrix4().set( m0, m1, m2, posX, m3, m4, m5, posY, m6, m7, m8, posZ, 0, 0, 0, 1 );
|
|
966
|
+
let fileName = lp.getRemainingString().trim().replace( /\\/g, '/' );
|
|
778
967
|
|
|
779
|
-
|
|
780
|
-
// This also allows to handle the embedded text files ("0 FILE" lines)
|
|
968
|
+
if ( loader.fileMap[ fileName ] ) {
|
|
781
969
|
|
|
782
|
-
|
|
970
|
+
// Found the subobject path in the preloaded file path map
|
|
971
|
+
fileName = loader.fileMap[ fileName ];
|
|
783
972
|
|
|
784
|
-
|
|
785
|
-
this.rootParseScope = this.newParseScopeLevel(); // Add default main triangle and line edge materials (used in pieces that can be coloured with a main color)
|
|
973
|
+
} else {
|
|
786
974
|
|
|
787
|
-
|
|
788
|
-
|
|
975
|
+
// Standardized subfolders
|
|
976
|
+
if ( fileName.startsWith( 's/' ) ) {
|
|
789
977
|
|
|
790
|
-
|
|
978
|
+
fileName = 'parts/' + fileName;
|
|
791
979
|
|
|
792
|
-
|
|
980
|
+
} else if ( fileName.startsWith( '48/' ) ) {
|
|
793
981
|
|
|
794
|
-
|
|
982
|
+
fileName = 'p/' + fileName;
|
|
795
983
|
|
|
796
|
-
|
|
984
|
+
}
|
|
797
985
|
|
|
798
|
-
|
|
986
|
+
}
|
|
799
987
|
|
|
800
|
-
|
|
801
|
-
|
|
988
|
+
subobjects.push( {
|
|
989
|
+
material: material,
|
|
990
|
+
colorCode: colorCode,
|
|
991
|
+
matrix: matrix,
|
|
992
|
+
fileName: fileName,
|
|
993
|
+
inverted: bfcInverted,
|
|
994
|
+
startingConstructionStep: startingConstructionStep
|
|
995
|
+
} );
|
|
996
|
+
bfcInverted = false;
|
|
997
|
+
break;
|
|
998
|
+
// Line type 2: Line segment
|
|
802
999
|
|
|
803
|
-
|
|
1000
|
+
case '2':
|
|
1001
|
+
colorCode = lp.getToken();
|
|
1002
|
+
material = getLocalMaterial( colorCode );
|
|
1003
|
+
v0 = lp.getVector();
|
|
1004
|
+
v1 = lp.getVector();
|
|
1005
|
+
segment = {
|
|
1006
|
+
material: material,
|
|
1007
|
+
colorCode: colorCode,
|
|
1008
|
+
vertices: [ v0, v1 ]
|
|
1009
|
+
};
|
|
1010
|
+
lineSegments.push( segment );
|
|
1011
|
+
break;
|
|
1012
|
+
// Line type 5: Conditional Line segment
|
|
804
1013
|
|
|
805
|
-
|
|
1014
|
+
case '5':
|
|
1015
|
+
colorCode = lp.getToken();
|
|
1016
|
+
material = getLocalMaterial( colorCode );
|
|
1017
|
+
v0 = lp.getVector();
|
|
1018
|
+
v1 = lp.getVector();
|
|
1019
|
+
c0 = lp.getVector();
|
|
1020
|
+
c1 = lp.getVector();
|
|
1021
|
+
segment = {
|
|
1022
|
+
material: material,
|
|
1023
|
+
colorCode: colorCode,
|
|
1024
|
+
vertices: [ v0, v1 ],
|
|
1025
|
+
controlPoints: [ c0, c1 ]
|
|
1026
|
+
};
|
|
1027
|
+
conditionalSegments.push( segment );
|
|
1028
|
+
break;
|
|
1029
|
+
// Line type 3: Triangle
|
|
806
1030
|
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
const colorLineRegex = /^0 !COLOUR/;
|
|
813
|
-
const lines = text.split( /[\n\r]/g );
|
|
814
|
-
const materials = [];
|
|
1031
|
+
case '3':
|
|
1032
|
+
colorCode = lp.getToken();
|
|
1033
|
+
material = getLocalMaterial( colorCode );
|
|
1034
|
+
ccw = bfcCCW;
|
|
1035
|
+
doubleSided = ! bfcCertified || ! bfcCull;
|
|
815
1036
|
|
|
816
|
-
|
|
1037
|
+
if ( ccw === true ) {
|
|
817
1038
|
|
|
818
|
-
|
|
1039
|
+
v0 = lp.getVector();
|
|
1040
|
+
v1 = lp.getVector();
|
|
1041
|
+
v2 = lp.getVector();
|
|
819
1042
|
|
|
820
|
-
|
|
1043
|
+
} else {
|
|
821
1044
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
1045
|
+
v2 = lp.getVector();
|
|
1046
|
+
v1 = lp.getVector();
|
|
1047
|
+
v0 = lp.getVector();
|
|
825
1048
|
|
|
826
|
-
|
|
1049
|
+
}
|
|
827
1050
|
|
|
828
|
-
|
|
1051
|
+
faces.push( {
|
|
1052
|
+
material: material,
|
|
1053
|
+
colorCode: colorCode,
|
|
1054
|
+
faceNormal: null,
|
|
1055
|
+
vertices: [ v0, v1, v2 ],
|
|
1056
|
+
normals: [ null, null, null ]
|
|
1057
|
+
} );
|
|
1058
|
+
totalFaces ++;
|
|
829
1059
|
|
|
830
|
-
|
|
1060
|
+
if ( doubleSided === true ) {
|
|
831
1061
|
|
|
832
|
-
|
|
1062
|
+
faces.push( {
|
|
1063
|
+
material: material,
|
|
1064
|
+
colorCode: colorCode,
|
|
1065
|
+
faceNormal: null,
|
|
1066
|
+
vertices: [ v2, v1, v0 ],
|
|
1067
|
+
normals: [ null, null, null ]
|
|
1068
|
+
} );
|
|
1069
|
+
totalFaces ++;
|
|
833
1070
|
|
|
834
|
-
|
|
1071
|
+
}
|
|
835
1072
|
|
|
836
|
-
|
|
1073
|
+
break;
|
|
1074
|
+
// Line type 4: Quadrilateral
|
|
837
1075
|
|
|
838
|
-
|
|
1076
|
+
case '4':
|
|
1077
|
+
colorCode = lp.getToken();
|
|
1078
|
+
material = getLocalMaterial( colorCode );
|
|
1079
|
+
ccw = bfcCCW;
|
|
1080
|
+
doubleSided = ! bfcCertified || ! bfcCull;
|
|
839
1081
|
|
|
840
|
-
|
|
1082
|
+
if ( ccw === true ) {
|
|
841
1083
|
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
fileLoader.load( url, text => {
|
|
1084
|
+
v0 = lp.getVector();
|
|
1085
|
+
v1 = lp.getVector();
|
|
1086
|
+
v2 = lp.getVector();
|
|
1087
|
+
v3 = lp.getVector();
|
|
847
1088
|
|
|
848
|
-
|
|
1089
|
+
} else {
|
|
849
1090
|
|
|
850
|
-
|
|
1091
|
+
v3 = lp.getVector();
|
|
1092
|
+
v2 = lp.getVector();
|
|
1093
|
+
v1 = lp.getVector();
|
|
1094
|
+
v0 = lp.getVector();
|
|
851
1095
|
|
|
852
|
-
|
|
1096
|
+
} // specifically place the triangle diagonal in the v0 and v1 slots so we can
|
|
1097
|
+
// account for the doubling of vertices later when smoothing normals.
|
|
853
1098
|
|
|
854
|
-
}, onProgress, onError );
|
|
855
1099
|
|
|
856
|
-
|
|
1100
|
+
faces.push( {
|
|
1101
|
+
material: material,
|
|
1102
|
+
colorCode: colorCode,
|
|
1103
|
+
faceNormal: null,
|
|
1104
|
+
vertices: [ v0, v1, v2, v3 ],
|
|
1105
|
+
normals: [ null, null, null, null ]
|
|
1106
|
+
} );
|
|
1107
|
+
totalFaces += 2;
|
|
857
1108
|
|
|
858
|
-
|
|
1109
|
+
if ( doubleSided === true ) {
|
|
859
1110
|
|
|
860
|
-
|
|
861
|
-
|
|
1111
|
+
faces.push( {
|
|
1112
|
+
material: material,
|
|
1113
|
+
colorCode: colorCode,
|
|
1114
|
+
faceNormal: null,
|
|
1115
|
+
vertices: [ v3, v2, v1, v0 ],
|
|
1116
|
+
normals: [ null, null, null, null ]
|
|
1117
|
+
} );
|
|
1118
|
+
totalFaces += 2;
|
|
862
1119
|
|
|
863
|
-
|
|
1120
|
+
}
|
|
864
1121
|
|
|
865
|
-
|
|
1122
|
+
break;
|
|
866
1123
|
|
|
867
|
-
|
|
1124
|
+
default:
|
|
1125
|
+
throw new Error( 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.' );
|
|
868
1126
|
|
|
869
|
-
|
|
1127
|
+
}
|
|
870
1128
|
|
|
871
|
-
|
|
872
|
-
this.rootParseScope = this.newParseScopeLevel( materials );
|
|
873
|
-
this.rootParseScope.isFromParse = false;
|
|
874
|
-
this.materials = materials;
|
|
875
|
-
return this;
|
|
1129
|
+
}
|
|
876
1130
|
|
|
877
|
-
|
|
1131
|
+
if ( parsingEmbeddedFiles ) {
|
|
878
1132
|
|
|
879
|
-
|
|
1133
|
+
this.setData( currentEmbeddedFileName, currentEmbeddedText );
|
|
880
1134
|
|
|
881
|
-
|
|
882
|
-
return this;
|
|
1135
|
+
}
|
|
883
1136
|
|
|
884
|
-
|
|
1137
|
+
return {
|
|
1138
|
+
faces,
|
|
1139
|
+
conditionalSegments,
|
|
1140
|
+
lineSegments,
|
|
1141
|
+
type,
|
|
1142
|
+
category,
|
|
1143
|
+
keywords,
|
|
1144
|
+
subobjects,
|
|
1145
|
+
totalFaces,
|
|
1146
|
+
startingConstructionStep,
|
|
1147
|
+
materials,
|
|
1148
|
+
fileName,
|
|
1149
|
+
group: null
|
|
1150
|
+
};
|
|
885
1151
|
|
|
886
|
-
|
|
1152
|
+
} // returns an (optionally cloned) instance of the data
|
|
887
1153
|
|
|
888
|
-
// Adds a new scope level, assign materials to it and returns it
|
|
889
|
-
const matLib = {};
|
|
890
1154
|
|
|
891
|
-
|
|
1155
|
+
getData( fileName, clone = true ) {
|
|
892
1156
|
|
|
893
|
-
|
|
1157
|
+
const key = fileName.toLowerCase();
|
|
1158
|
+
const result = this._cache[ key ];
|
|
894
1159
|
|
|
895
|
-
|
|
896
|
-
matLib[ material.userData.code ] = material;
|
|
1160
|
+
if ( result === null || result instanceof Promise ) {
|
|
897
1161
|
|
|
898
|
-
|
|
1162
|
+
return null;
|
|
899
1163
|
|
|
900
1164
|
}
|
|
901
1165
|
|
|
902
|
-
|
|
903
|
-
parentScope: parentScope,
|
|
904
|
-
lib: matLib,
|
|
905
|
-
url: null,
|
|
906
|
-
// Subobjects
|
|
907
|
-
subobjects: null,
|
|
908
|
-
numSubobjects: 0,
|
|
909
|
-
subobjectIndex: 0,
|
|
910
|
-
inverted: false,
|
|
911
|
-
category: null,
|
|
912
|
-
keywords: null,
|
|
913
|
-
// Current subobject
|
|
914
|
-
currentFileName: null,
|
|
915
|
-
mainColourCode: parentScope ? parentScope.mainColourCode : '16',
|
|
916
|
-
mainEdgeColourCode: parentScope ? parentScope.mainEdgeColourCode : '24',
|
|
917
|
-
currentMatrix: new THREE.Matrix4(),
|
|
918
|
-
matrix: new THREE.Matrix4(),
|
|
919
|
-
type: 'Model',
|
|
920
|
-
groupObject: null,
|
|
921
|
-
// If false, it is a root material scope previous to parse
|
|
922
|
-
isFromParse: true,
|
|
923
|
-
faces: [],
|
|
924
|
-
lineSegments: [],
|
|
925
|
-
conditionalSegments: [],
|
|
926
|
-
totalFaces: 0,
|
|
927
|
-
// If true, this object is the start of a construction step
|
|
928
|
-
startingConstructionStep: false
|
|
929
|
-
};
|
|
930
|
-
return newParseScope;
|
|
1166
|
+
if ( clone ) {
|
|
931
1167
|
|
|
932
|
-
|
|
1168
|
+
return this.cloneResult( result );
|
|
933
1169
|
|
|
934
|
-
|
|
1170
|
+
} else {
|
|
935
1171
|
|
|
936
|
-
|
|
937
|
-
const matLib = parseScope.lib;
|
|
1172
|
+
return result;
|
|
938
1173
|
|
|
939
|
-
|
|
1174
|
+
}
|
|
940
1175
|
|
|
941
|
-
|
|
1176
|
+
} // kicks off a fetch and parse of the requested data if it hasn't already been loaded. Returns when
|
|
1177
|
+
// the data is ready to use and can be retrieved synchronously with "getData".
|
|
942
1178
|
|
|
943
|
-
}
|
|
944
1179
|
|
|
945
|
-
|
|
946
|
-
return this;
|
|
1180
|
+
async ensureDataLoaded( fileName ) {
|
|
947
1181
|
|
|
948
|
-
|
|
1182
|
+
const key = fileName.toLowerCase();
|
|
1183
|
+
|
|
1184
|
+
if ( ! ( key in this._cache ) ) {
|
|
949
1185
|
|
|
950
|
-
|
|
1186
|
+
// replace the promise with a copy of the parsed data for immediate processing
|
|
1187
|
+
this._cache[ key ] = this.fetchData( fileName ).then( text => {
|
|
951
1188
|
|
|
952
|
-
|
|
953
|
-
|
|
1189
|
+
const info = this.parse( text, fileName );
|
|
1190
|
+
this._cache[ key ] = info;
|
|
1191
|
+
return info;
|
|
954
1192
|
|
|
955
|
-
|
|
956
|
-
const colour = colourCode.substring( 3 );
|
|
957
|
-
return this.parseColourMetaDirective( new LineParser( 'Direct_Color_' + colour + ' CODE -1 VALUE #' + colour + ' EDGE #' + colour + '' ) );
|
|
1193
|
+
} );
|
|
958
1194
|
|
|
959
1195
|
}
|
|
960
1196
|
|
|
961
|
-
|
|
1197
|
+
await this._cache[ key ];
|
|
962
1198
|
|
|
963
|
-
|
|
1199
|
+
} // sets the data in the cache from parsed data
|
|
964
1200
|
|
|
965
|
-
if ( material ) {
|
|
966
1201
|
|
|
967
|
-
|
|
1202
|
+
setData( fileName, text ) {
|
|
968
1203
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
parseScope = parseScope.parentScope;
|
|
1204
|
+
const key = fileName.toLowerCase();
|
|
1205
|
+
this._cache[ key ] = this.parse( text, fileName );
|
|
972
1206
|
|
|
973
|
-
|
|
1207
|
+
}
|
|
974
1208
|
|
|
975
|
-
|
|
1209
|
+
} // returns the material for an associated color code. If the color code is 16 for a face or 24 for
|
|
1210
|
+
// an edge then the passthroughColorCode is used.
|
|
976
1211
|
|
|
977
1212
|
|
|
978
|
-
|
|
1213
|
+
function getMaterialFromCode( colorCode, parentColorCode, materialHierarchy, forEdge ) {
|
|
979
1214
|
|
|
980
|
-
|
|
1215
|
+
const isPassthrough = ! forEdge && colorCode === MAIN_COLOUR_CODE || forEdge && colorCode === MAIN_EDGE_COLOUR_CODE;
|
|
981
1216
|
|
|
982
|
-
|
|
1217
|
+
if ( isPassthrough ) {
|
|
983
1218
|
|
|
984
|
-
|
|
985
|
-
let code = null; // Triangle and line colours
|
|
1219
|
+
colorCode = parentColorCode;
|
|
986
1220
|
|
|
987
|
-
|
|
988
|
-
let edgeColour = 0xFF00FF; // Transparency
|
|
1221
|
+
}
|
|
989
1222
|
|
|
990
|
-
|
|
991
|
-
let isTransparent = false; // Self-illumination:
|
|
1223
|
+
return materialHierarchy[ colorCode ] || null;
|
|
992
1224
|
|
|
993
|
-
|
|
994
|
-
let finishType = FINISH_TYPE_DEFAULT;
|
|
995
|
-
let edgeMaterial = null;
|
|
996
|
-
const name = lineParser.getToken();
|
|
1225
|
+
} // Class used to parse and build LDraw parts as three.js objects and cache them if they're a "Part" type.
|
|
997
1226
|
|
|
998
|
-
if ( ! name ) {
|
|
999
1227
|
|
|
1000
|
-
|
|
1228
|
+
class LDrawPartsGeometryCache {
|
|
1001
1229
|
|
|
1002
|
-
|
|
1230
|
+
constructor( loader ) {
|
|
1003
1231
|
|
|
1232
|
+
this.loader = loader;
|
|
1233
|
+
this.parseCache = new LDrawParsedCache( loader );
|
|
1234
|
+
this._cache = {};
|
|
1004
1235
|
|
|
1005
|
-
|
|
1236
|
+
} // Convert the given file information into a mesh by processing subobjects.
|
|
1006
1237
|
|
|
1007
|
-
while ( true ) {
|
|
1008
1238
|
|
|
1009
|
-
|
|
1239
|
+
async processIntoMesh( info ) {
|
|
1010
1240
|
|
|
1011
|
-
|
|
1241
|
+
const loader = this.loader;
|
|
1242
|
+
const parseCache = this.parseCache;
|
|
1243
|
+
const faceMaterials = new Set(); // Processes the part subobject information to load child parts and merge geometry onto part
|
|
1244
|
+
// piece object.
|
|
1012
1245
|
|
|
1013
|
-
|
|
1246
|
+
const processInfoSubobjects = async ( info, subobject = null ) => {
|
|
1014
1247
|
|
|
1015
|
-
|
|
1248
|
+
const subobjects = info.subobjects;
|
|
1249
|
+
const promises = []; // Trigger load of all subobjects. If a subobject isn't a primitive then load it as a separate
|
|
1250
|
+
// group which lets instruction steps apply correctly.
|
|
1016
1251
|
|
|
1017
|
-
|
|
1252
|
+
for ( let i = 0, l = subobjects.length; i < l; i ++ ) {
|
|
1018
1253
|
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
break;
|
|
1254
|
+
const subobject = subobjects[ i ];
|
|
1255
|
+
const promise = parseCache.ensureDataLoaded( subobject.fileName ).then( () => {
|
|
1022
1256
|
|
|
1023
|
-
|
|
1024
|
-
colour = lineParser.getToken();
|
|
1257
|
+
const subobjectInfo = parseCache.getData( subobject.fileName, false );
|
|
1025
1258
|
|
|
1026
|
-
if (
|
|
1259
|
+
if ( ! isPrimitiveType( subobjectInfo.type ) ) {
|
|
1027
1260
|
|
|
1028
|
-
|
|
1261
|
+
return this.loadModel( subobject.fileName ).catch( error => {
|
|
1029
1262
|
|
|
1030
|
-
|
|
1263
|
+
console.warn( error );
|
|
1264
|
+
return null;
|
|
1031
1265
|
|
|
1032
|
-
|
|
1266
|
+
} );
|
|
1033
1267
|
|
|
1034
1268
|
}
|
|
1035
1269
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
case 'EDGE':
|
|
1039
|
-
edgeColour = lineParser.getToken();
|
|
1040
|
-
|
|
1041
|
-
if ( edgeColour.startsWith( '0x' ) ) {
|
|
1270
|
+
return processInfoSubobjects( parseCache.getData( subobject.fileName ), subobject );
|
|
1042
1271
|
|
|
1043
|
-
|
|
1272
|
+
} );
|
|
1273
|
+
promises.push( promise );
|
|
1044
1274
|
|
|
1045
|
-
|
|
1275
|
+
}
|
|
1046
1276
|
|
|
1047
|
-
|
|
1048
|
-
|
|
1277
|
+
const group = new THREE.Group();
|
|
1278
|
+
group.userData.category = info.category;
|
|
1279
|
+
group.userData.keywords = info.keywords;
|
|
1280
|
+
info.group = group;
|
|
1281
|
+
const subobjectInfos = await Promise.all( promises );
|
|
1049
1282
|
|
|
1050
|
-
|
|
1283
|
+
for ( let i = 0, l = subobjectInfos.length; i < l; i ++ ) {
|
|
1051
1284
|
|
|
1052
|
-
|
|
1285
|
+
const subobject = info.subobjects[ i ];
|
|
1286
|
+
const subobjectInfo = subobjectInfos[ i ];
|
|
1053
1287
|
|
|
1054
|
-
|
|
1288
|
+
if ( subobjectInfo === null ) {
|
|
1055
1289
|
|
|
1290
|
+
// the subobject failed to load
|
|
1291
|
+
continue;
|
|
1056
1292
|
|
|
1057
|
-
|
|
1293
|
+
} // if the subobject was loaded as a separate group then apply the parent scopes materials
|
|
1058
1294
|
|
|
1059
|
-
}
|
|
1060
1295
|
|
|
1061
|
-
|
|
1296
|
+
if ( subobjectInfo.isGroup ) {
|
|
1062
1297
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1298
|
+
const subobjectGroup = subobjectInfo;
|
|
1299
|
+
subobject.matrix.decompose( subobjectGroup.position, subobjectGroup.quaternion, subobjectGroup.scale );
|
|
1300
|
+
subobjectGroup.userData.startingConstructionStep = subobject.startingConstructionStep;
|
|
1301
|
+
subobjectGroup.name = subobject.fileName;
|
|
1302
|
+
loader.applyMaterialsToMesh( subobjectGroup, subobject.colorCode, info.materials );
|
|
1303
|
+
group.add( subobjectGroup );
|
|
1304
|
+
continue;
|
|
1065
1305
|
|
|
1066
|
-
|
|
1306
|
+
} // add the subobject group if it has children in case it has both children and primitives
|
|
1067
1307
|
|
|
1068
|
-
throw 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.';
|
|
1069
1308
|
|
|
1070
|
-
|
|
1309
|
+
if ( subobjectInfo.group.children.length ) {
|
|
1071
1310
|
|
|
1072
|
-
|
|
1311
|
+
group.add( subobjectInfo.group );
|
|
1073
1312
|
|
|
1074
|
-
|
|
1313
|
+
} // transform the primitives into the local space of the parent piece and append them to
|
|
1314
|
+
// to the parent primitives list.
|
|
1075
1315
|
|
|
1076
|
-
isTransparent = true;
|
|
1077
1316
|
|
|
1078
|
-
|
|
1317
|
+
const parentLineSegments = info.lineSegments;
|
|
1318
|
+
const parentConditionalSegments = info.conditionalSegments;
|
|
1319
|
+
const parentFaces = info.faces;
|
|
1320
|
+
const lineSegments = subobjectInfo.lineSegments;
|
|
1321
|
+
const conditionalSegments = subobjectInfo.conditionalSegments;
|
|
1322
|
+
const faces = subobjectInfo.faces;
|
|
1323
|
+
const matrix = subobject.matrix;
|
|
1324
|
+
const inverted = subobject.inverted;
|
|
1325
|
+
const matrixScaleInverted = matrix.determinant() < 0;
|
|
1326
|
+
const colorCode = subobject.colorCode;
|
|
1327
|
+
const lineColorCode = colorCode === MAIN_COLOUR_CODE ? MAIN_EDGE_COLOUR_CODE : colorCode;
|
|
1079
1328
|
|
|
1080
|
-
|
|
1329
|
+
for ( let i = 0, l = lineSegments.length; i < l; i ++ ) {
|
|
1081
1330
|
|
|
1082
|
-
|
|
1083
|
-
|
|
1331
|
+
const ls = lineSegments[ i ];
|
|
1332
|
+
const vertices = ls.vertices;
|
|
1333
|
+
vertices[ 0 ].applyMatrix4( matrix );
|
|
1334
|
+
vertices[ 1 ].applyMatrix4( matrix );
|
|
1335
|
+
ls.colorCode = ls.colorCode === MAIN_EDGE_COLOUR_CODE ? lineColorCode : ls.colorCode;
|
|
1336
|
+
ls.material = ls.material || getMaterialFromCode( ls.colorCode, ls.colorCode, info.materials, true );
|
|
1337
|
+
parentLineSegments.push( ls );
|
|
1084
1338
|
|
|
1085
|
-
|
|
1339
|
+
}
|
|
1086
1340
|
|
|
1087
|
-
|
|
1341
|
+
for ( let i = 0, l = conditionalSegments.length; i < l; i ++ ) {
|
|
1088
1342
|
|
|
1089
|
-
|
|
1343
|
+
const os = conditionalSegments[ i ];
|
|
1344
|
+
const vertices = os.vertices;
|
|
1345
|
+
const controlPoints = os.controlPoints;
|
|
1346
|
+
vertices[ 0 ].applyMatrix4( matrix );
|
|
1347
|
+
vertices[ 1 ].applyMatrix4( matrix );
|
|
1348
|
+
controlPoints[ 0 ].applyMatrix4( matrix );
|
|
1349
|
+
controlPoints[ 1 ].applyMatrix4( matrix );
|
|
1350
|
+
os.colorCode = os.colorCode === MAIN_EDGE_COLOUR_CODE ? lineColorCode : os.colorCode;
|
|
1351
|
+
os.material = os.material || getMaterialFromCode( os.colorCode, os.colorCode, info.materials, true );
|
|
1352
|
+
parentConditionalSegments.push( os );
|
|
1090
1353
|
|
|
1091
|
-
|
|
1092
|
-
break;
|
|
1354
|
+
}
|
|
1093
1355
|
|
|
1094
|
-
|
|
1095
|
-
finishType = FINISH_TYPE_CHROME;
|
|
1096
|
-
break;
|
|
1356
|
+
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
1097
1357
|
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
break;
|
|
1358
|
+
const tri = faces[ i ];
|
|
1359
|
+
const vertices = tri.vertices;
|
|
1101
1360
|
|
|
1102
|
-
|
|
1103
|
-
finishType = FINISH_TYPE_RUBBER;
|
|
1104
|
-
break;
|
|
1361
|
+
for ( let i = 0, l = vertices.length; i < l; i ++ ) {
|
|
1105
1362
|
|
|
1106
|
-
|
|
1107
|
-
finishType = FINISH_TYPE_MATTE_METALLIC;
|
|
1108
|
-
break;
|
|
1363
|
+
vertices[ i ].applyMatrix4( matrix );
|
|
1109
1364
|
|
|
1110
|
-
|
|
1111
|
-
finishType = FINISH_TYPE_METAL;
|
|
1112
|
-
break;
|
|
1365
|
+
}
|
|
1113
1366
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1367
|
+
tri.colorCode = tri.colorCode === MAIN_COLOUR_CODE ? colorCode : tri.colorCode;
|
|
1368
|
+
tri.material = tri.material || getMaterialFromCode( tri.colorCode, colorCode, info.materials, false );
|
|
1369
|
+
faceMaterials.add( tri.colorCode ); // If the scale of the object is negated then the triangle winding order
|
|
1370
|
+
// needs to be flipped.
|
|
1118
1371
|
|
|
1119
|
-
|
|
1120
|
-
throw 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.';
|
|
1121
|
-
break;
|
|
1372
|
+
if ( matrixScaleInverted !== inverted ) {
|
|
1122
1373
|
|
|
1123
|
-
|
|
1374
|
+
vertices.reverse();
|
|
1124
1375
|
|
|
1125
|
-
|
|
1376
|
+
}
|
|
1126
1377
|
|
|
1127
|
-
|
|
1378
|
+
parentFaces.push( tri );
|
|
1128
1379
|
|
|
1129
|
-
|
|
1380
|
+
}
|
|
1130
1381
|
|
|
1131
|
-
|
|
1132
|
-
material = new THREE.MeshStandardMaterial( {
|
|
1133
|
-
color: colour,
|
|
1134
|
-
roughness: 0.3,
|
|
1135
|
-
metalness: 0
|
|
1136
|
-
} );
|
|
1137
|
-
break;
|
|
1382
|
+
info.totalFaces += subobjectInfo.totalFaces;
|
|
1138
1383
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
material = new THREE.MeshStandardMaterial( {
|
|
1142
|
-
color: colour,
|
|
1143
|
-
roughness: 0.3,
|
|
1144
|
-
metalness: 0.25
|
|
1145
|
-
} );
|
|
1146
|
-
break;
|
|
1384
|
+
} // Apply the parent subobjects pass through material code to this object. This is done several times due
|
|
1385
|
+
// to material scoping.
|
|
1147
1386
|
|
|
1148
|
-
case FINISH_TYPE_CHROME:
|
|
1149
|
-
// Mirror finish surface
|
|
1150
|
-
material = new THREE.MeshStandardMaterial( {
|
|
1151
|
-
color: colour,
|
|
1152
|
-
roughness: 0,
|
|
1153
|
-
metalness: 1
|
|
1154
|
-
} );
|
|
1155
|
-
break;
|
|
1156
1387
|
|
|
1157
|
-
|
|
1158
|
-
// Rubber finish
|
|
1159
|
-
material = new THREE.MeshStandardMaterial( {
|
|
1160
|
-
color: colour,
|
|
1161
|
-
roughness: 0.9,
|
|
1162
|
-
metalness: 0
|
|
1163
|
-
} );
|
|
1164
|
-
break;
|
|
1388
|
+
if ( subobject ) {
|
|
1165
1389
|
|
|
1166
|
-
|
|
1167
|
-
// Brushed metal finish
|
|
1168
|
-
material = new THREE.MeshStandardMaterial( {
|
|
1169
|
-
color: colour,
|
|
1170
|
-
roughness: 0.8,
|
|
1171
|
-
metalness: 0.4
|
|
1172
|
-
} );
|
|
1173
|
-
break;
|
|
1390
|
+
loader.applyMaterialsToMesh( group, subobject.colorCode, info.materials );
|
|
1174
1391
|
|
|
1175
|
-
|
|
1176
|
-
// Average metal finish
|
|
1177
|
-
material = new THREE.MeshStandardMaterial( {
|
|
1178
|
-
color: colour,
|
|
1179
|
-
roughness: 0.2,
|
|
1180
|
-
metalness: 0.85
|
|
1181
|
-
} );
|
|
1182
|
-
break;
|
|
1392
|
+
}
|
|
1183
1393
|
|
|
1184
|
-
|
|
1185
|
-
// Should not happen
|
|
1186
|
-
break;
|
|
1394
|
+
return info;
|
|
1187
1395
|
|
|
1188
|
-
}
|
|
1396
|
+
}; // Track material use to see if we need to use the normal smooth slow path for hard edges.
|
|
1189
1397
|
|
|
1190
|
-
material.transparent = isTransparent;
|
|
1191
|
-
material.premultipliedAlpha = true;
|
|
1192
|
-
material.opacity = alpha;
|
|
1193
|
-
material.depthWrite = ! isTransparent;
|
|
1194
|
-
material.polygonOffset = true;
|
|
1195
|
-
material.polygonOffsetFactor = 1;
|
|
1196
1398
|
|
|
1197
|
-
|
|
1399
|
+
for ( let i = 0, l = info.faces; i < l; i ++ ) {
|
|
1198
1400
|
|
|
1199
|
-
|
|
1401
|
+
faceMaterials.add( info.faces[ i ].colorCode );
|
|
1200
1402
|
|
|
1201
1403
|
}
|
|
1202
1404
|
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
// This is the material used for edges
|
|
1206
|
-
edgeMaterial = new THREE.LineBasicMaterial( {
|
|
1207
|
-
color: edgeColour,
|
|
1208
|
-
transparent: isTransparent,
|
|
1209
|
-
opacity: alpha,
|
|
1210
|
-
depthWrite: ! isTransparent
|
|
1211
|
-
} );
|
|
1212
|
-
edgeMaterial.userData.code = code;
|
|
1213
|
-
edgeMaterial.name = name + ' - Edge'; // This is the material used for conditional edges
|
|
1214
|
-
|
|
1215
|
-
edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial( {
|
|
1216
|
-
fog: true,
|
|
1217
|
-
transparent: isTransparent,
|
|
1218
|
-
depthWrite: ! isTransparent,
|
|
1219
|
-
color: edgeColour,
|
|
1220
|
-
opacity: alpha
|
|
1221
|
-
} );
|
|
1405
|
+
await processInfoSubobjects( info );
|
|
1222
1406
|
|
|
1223
|
-
|
|
1407
|
+
if ( loader.smoothNormals ) {
|
|
1224
1408
|
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
return material;
|
|
1409
|
+
const checkSubSegments = faceMaterials.size > 1;
|
|
1410
|
+
generateFaceNormals( info.faces );
|
|
1411
|
+
smoothNormals( info.faces, info.lineSegments, checkSubSegments );
|
|
1229
1412
|
|
|
1230
|
-
|
|
1413
|
+
} // Add the primitive objects and metadata.
|
|
1231
1414
|
|
|
1232
1415
|
|
|
1233
|
-
|
|
1416
|
+
const group = info.group;
|
|
1234
1417
|
|
|
1235
|
-
|
|
1236
|
-
const currentParseScope = parseScope;
|
|
1237
|
-
const parentParseScope = currentParseScope.parentScope; // Main colour codes passed to this subobject (or default codes 16 and 24 if it is the root object)
|
|
1418
|
+
if ( info.faces.length > 0 ) {
|
|
1238
1419
|
|
|
1239
|
-
|
|
1240
|
-
const mainEdgeColourCode = currentParseScope.mainEdgeColourCode; // Parse result variables
|
|
1420
|
+
group.add( createObject( info.faces, 3, false, info.totalFaces ) );
|
|
1241
1421
|
|
|
1242
|
-
|
|
1243
|
-
let lineSegments;
|
|
1244
|
-
let conditionalSegments;
|
|
1245
|
-
const subobjects = [];
|
|
1246
|
-
let category = null;
|
|
1247
|
-
let keywords = null;
|
|
1422
|
+
}
|
|
1248
1423
|
|
|
1249
|
-
if (
|
|
1424
|
+
if ( info.lineSegments.length > 0 ) {
|
|
1250
1425
|
|
|
1251
|
-
|
|
1252
|
-
text = text.replace( /\r\n/g, '\n' );
|
|
1426
|
+
group.add( createObject( info.lineSegments, 2 ) );
|
|
1253
1427
|
|
|
1254
1428
|
}
|
|
1255
1429
|
|
|
1256
|
-
|
|
1257
|
-
const numLines = lines.length;
|
|
1258
|
-
let parsingEmbeddedFiles = false;
|
|
1259
|
-
let currentEmbeddedFileName = null;
|
|
1260
|
-
let currentEmbeddedText = null;
|
|
1261
|
-
let bfcCertified = false;
|
|
1262
|
-
let bfcCCW = true;
|
|
1263
|
-
let bfcInverted = false;
|
|
1264
|
-
let bfcCull = true;
|
|
1265
|
-
let type = '';
|
|
1266
|
-
let startingConstructionStep = false;
|
|
1267
|
-
const scope = this;
|
|
1268
|
-
|
|
1269
|
-
function parseColourCode( lineParser, forEdge ) {
|
|
1430
|
+
if ( info.conditionalSegments.length > 0 ) {
|
|
1270
1431
|
|
|
1271
|
-
|
|
1272
|
-
let colourCode = lineParser.getToken();
|
|
1432
|
+
group.add( createObject( info.conditionalSegments, 2, true ) );
|
|
1273
1433
|
|
|
1274
|
-
|
|
1434
|
+
}
|
|
1275
1435
|
|
|
1276
|
-
|
|
1436
|
+
return group;
|
|
1277
1437
|
|
|
1278
|
-
|
|
1438
|
+
}
|
|
1279
1439
|
|
|
1280
|
-
|
|
1440
|
+
hasCachedModel( fileName ) {
|
|
1281
1441
|
|
|
1282
|
-
|
|
1442
|
+
return fileName !== null && fileName.toLowerCase() in this._cache;
|
|
1283
1443
|
|
|
1284
|
-
|
|
1444
|
+
}
|
|
1285
1445
|
|
|
1286
|
-
|
|
1446
|
+
async getCachedModel( fileName ) {
|
|
1287
1447
|
|
|
1288
|
-
|
|
1448
|
+
if ( fileName !== null && this.hasCachedModel( fileName ) ) {
|
|
1289
1449
|
|
|
1290
|
-
|
|
1450
|
+
const key = fileName.toLowerCase();
|
|
1451
|
+
const group = await this._cache[ key ];
|
|
1452
|
+
return group.clone();
|
|
1291
1453
|
|
|
1292
|
-
|
|
1454
|
+
} else {
|
|
1293
1455
|
|
|
1294
|
-
return
|
|
1456
|
+
return null;
|
|
1295
1457
|
|
|
1296
1458
|
}
|
|
1297
1459
|
|
|
1298
|
-
|
|
1460
|
+
} // Loads and parses the model with the given file name. Returns a cached copy if available.
|
|
1299
1461
|
|
|
1300
|
-
const v = new THREE.Vector3( parseFloat( lp.getToken() ), parseFloat( lp.getToken() ), parseFloat( lp.getToken() ) );
|
|
1301
1462
|
|
|
1302
|
-
|
|
1463
|
+
async loadModel( fileName ) {
|
|
1303
1464
|
|
|
1304
|
-
|
|
1465
|
+
const parseCache = this.parseCache;
|
|
1466
|
+
const key = fileName.toLowerCase();
|
|
1305
1467
|
|
|
1306
|
-
|
|
1468
|
+
if ( this.hasCachedModel( fileName ) ) {
|
|
1307
1469
|
|
|
1308
|
-
|
|
1470
|
+
// Return cached model if available.
|
|
1471
|
+
return this.getCachedModel( fileName );
|
|
1309
1472
|
|
|
1310
|
-
}
|
|
1473
|
+
} else {
|
|
1311
1474
|
|
|
1475
|
+
// Otherwise parse a new model.
|
|
1476
|
+
// Ensure the file data is loaded and pre parsed.
|
|
1477
|
+
await parseCache.ensureDataLoaded( fileName );
|
|
1478
|
+
const info = parseCache.getData( fileName );
|
|
1479
|
+
const promise = this.processIntoMesh( info ); // Now that the file has loaded it's possible that another part parse has been waiting in parallel
|
|
1480
|
+
// so check the cache again to see if it's been added since the last async operation so we don't
|
|
1481
|
+
// do unnecessary work.
|
|
1312
1482
|
|
|
1313
|
-
|
|
1483
|
+
if ( this.hasCachedModel( fileName ) ) {
|
|
1314
1484
|
|
|
1315
|
-
|
|
1316
|
-
if ( line.length === 0 ) continue;
|
|
1485
|
+
return this.getCachedModel( fileName );
|
|
1317
1486
|
|
|
1318
|
-
if
|
|
1487
|
+
} // Cache object if it's a part so it can be reused later.
|
|
1319
1488
|
|
|
1320
|
-
if ( line.startsWith( '0 FILE ' ) ) {
|
|
1321
1489
|
|
|
1322
|
-
|
|
1323
|
-
this.cache.setData( currentEmbeddedFileName.toLowerCase(), currentEmbeddedText ); // New embedded text file
|
|
1490
|
+
if ( isPartType( info.type ) ) {
|
|
1324
1491
|
|
|
1325
|
-
|
|
1326
|
-
currentEmbeddedText = '';
|
|
1492
|
+
this._cache[ key ] = promise;
|
|
1327
1493
|
|
|
1328
|
-
|
|
1494
|
+
} // return a copy
|
|
1329
1495
|
|
|
1330
|
-
currentEmbeddedText += line + '\n';
|
|
1331
1496
|
|
|
1332
|
-
|
|
1497
|
+
const group = await promise;
|
|
1498
|
+
return group.clone();
|
|
1333
1499
|
|
|
1334
|
-
|
|
1500
|
+
}
|
|
1335
1501
|
|
|
1336
|
-
|
|
1502
|
+
} // parses the given model text into a renderable object. Returns cached copy if available.
|
|
1337
1503
|
|
|
1338
|
-
const lp = new LineParser( line, lineIndex + 1 );
|
|
1339
|
-
lp.seekNonSpace();
|
|
1340
1504
|
|
|
1341
|
-
|
|
1505
|
+
async parseModel( text ) {
|
|
1342
1506
|
|
|
1343
|
-
|
|
1344
|
-
|
|
1507
|
+
const parseCache = this.parseCache;
|
|
1508
|
+
const info = parseCache.parse( text );
|
|
1345
1509
|
|
|
1346
|
-
|
|
1510
|
+
if ( isPartType( info.type ) && this.hasCachedModel( info.fileName ) ) {
|
|
1347
1511
|
|
|
1512
|
+
return this.getCachedModel( info.fileName );
|
|
1348
1513
|
|
|
1349
|
-
|
|
1350
|
-
let material;
|
|
1351
|
-
let segment;
|
|
1352
|
-
let inverted;
|
|
1353
|
-
let ccw;
|
|
1354
|
-
let doubleSided;
|
|
1355
|
-
let v0, v1, v2, v3, c0, c1, faceNormal;
|
|
1514
|
+
}
|
|
1356
1515
|
|
|
1357
|
-
|
|
1516
|
+
return this.processIntoMesh( info );
|
|
1358
1517
|
|
|
1359
|
-
|
|
1360
|
-
case '0':
|
|
1361
|
-
// Parse meta directive
|
|
1362
|
-
const meta = lp.getToken();
|
|
1518
|
+
}
|
|
1363
1519
|
|
|
1364
|
-
|
|
1520
|
+
}
|
|
1365
1521
|
|
|
1366
|
-
|
|
1522
|
+
function sortByMaterial( a, b ) {
|
|
1367
1523
|
|
|
1368
|
-
|
|
1369
|
-
type = lp.getToken();
|
|
1370
|
-
currentParseScope.type = type; // If the scale of the object is negated then the triangle winding order
|
|
1371
|
-
// needs to be flipped.
|
|
1524
|
+
if ( a.colorCode === b.colorCode ) {
|
|
1372
1525
|
|
|
1373
|
-
|
|
1526
|
+
return 0;
|
|
1374
1527
|
|
|
1375
|
-
|
|
1528
|
+
}
|
|
1376
1529
|
|
|
1377
|
-
|
|
1530
|
+
if ( a.colorCode < b.colorCode ) {
|
|
1378
1531
|
|
|
1379
|
-
|
|
1380
|
-
lineSegments = currentParseScope.lineSegments;
|
|
1381
|
-
conditionalSegments = currentParseScope.conditionalSegments;
|
|
1382
|
-
break;
|
|
1532
|
+
return - 1;
|
|
1383
1533
|
|
|
1384
|
-
|
|
1385
|
-
material = this.parseColourMetaDirective( lp );
|
|
1534
|
+
}
|
|
1386
1535
|
|
|
1387
|
-
|
|
1536
|
+
return 1;
|
|
1388
1537
|
|
|
1389
|
-
|
|
1538
|
+
}
|
|
1390
1539
|
|
|
1391
|
-
|
|
1540
|
+
function createObject( elements, elementSize, isConditionalSegments = false, totalElements = null ) {
|
|
1392
1541
|
|
|
1393
|
-
|
|
1542
|
+
// Creates a THREE.LineSegments (elementSize = 2) or a THREE.Mesh (elementSize = 3 )
|
|
1543
|
+
// With per face / segment material, implemented with mesh groups and materials array
|
|
1544
|
+
// Sort the faces or line segments by color code to make later the mesh groups
|
|
1545
|
+
elements.sort( sortByMaterial );
|
|
1394
1546
|
|
|
1395
|
-
|
|
1547
|
+
if ( totalElements === null ) {
|
|
1396
1548
|
|
|
1397
|
-
|
|
1549
|
+
totalElements = elements.length;
|
|
1398
1550
|
|
|
1399
|
-
|
|
1400
|
-
category = lp.getToken();
|
|
1401
|
-
break;
|
|
1551
|
+
}
|
|
1402
1552
|
|
|
1403
|
-
|
|
1404
|
-
|
|
1553
|
+
const positions = new Float32Array( elementSize * totalElements * 3 );
|
|
1554
|
+
const normals = elementSize === 3 ? new Float32Array( elementSize * totalElements * 3 ) : null;
|
|
1555
|
+
const materials = [];
|
|
1556
|
+
const quadArray = new Array( 6 );
|
|
1557
|
+
const bufferGeometry = new THREE.BufferGeometry();
|
|
1558
|
+
let prevMaterial = null;
|
|
1559
|
+
let index0 = 0;
|
|
1560
|
+
let numGroupVerts = 0;
|
|
1561
|
+
let offset = 0;
|
|
1405
1562
|
|
|
1406
|
-
|
|
1563
|
+
for ( let iElem = 0, nElem = elements.length; iElem < nElem; iElem ++ ) {
|
|
1407
1564
|
|
|
1408
|
-
|
|
1565
|
+
const elem = elements[ iElem ];
|
|
1566
|
+
let vertices = elem.vertices;
|
|
1409
1567
|
|
|
1410
|
-
|
|
1568
|
+
if ( vertices.length === 4 ) {
|
|
1411
1569
|
|
|
1412
|
-
|
|
1570
|
+
quadArray[ 0 ] = vertices[ 0 ];
|
|
1571
|
+
quadArray[ 1 ] = vertices[ 1 ];
|
|
1572
|
+
quadArray[ 2 ] = vertices[ 2 ];
|
|
1573
|
+
quadArray[ 3 ] = vertices[ 0 ];
|
|
1574
|
+
quadArray[ 4 ] = vertices[ 2 ];
|
|
1575
|
+
quadArray[ 5 ] = vertices[ 3 ];
|
|
1576
|
+
vertices = quadArray;
|
|
1413
1577
|
|
|
1414
|
-
|
|
1578
|
+
}
|
|
1415
1579
|
|
|
1416
|
-
|
|
1580
|
+
for ( let j = 0, l = vertices.length; j < l; j ++ ) {
|
|
1417
1581
|
|
|
1418
|
-
|
|
1582
|
+
const v = vertices[ j ];
|
|
1583
|
+
const index = offset + j * 3;
|
|
1584
|
+
positions[ index + 0 ] = v.x;
|
|
1585
|
+
positions[ index + 1 ] = v.y;
|
|
1586
|
+
positions[ index + 2 ] = v.z;
|
|
1419
1587
|
|
|
1420
|
-
|
|
1588
|
+
} // create the normals array if this is a set of faces
|
|
1421
1589
|
|
|
1422
|
-
break;
|
|
1423
1590
|
|
|
1424
|
-
|
|
1425
|
-
if ( lineIndex > 0 ) {
|
|
1591
|
+
if ( elementSize === 3 ) {
|
|
1426
1592
|
|
|
1427
|
-
|
|
1428
|
-
parsingEmbeddedFiles = true;
|
|
1429
|
-
currentEmbeddedFileName = lp.getRemainingString();
|
|
1430
|
-
currentEmbeddedText = '';
|
|
1431
|
-
bfcCertified = false;
|
|
1432
|
-
bfcCCW = true;
|
|
1593
|
+
if ( ! elem.faceNormal ) {
|
|
1433
1594
|
|
|
1434
|
-
|
|
1595
|
+
const v0 = vertices[ 0 ];
|
|
1596
|
+
const v1 = vertices[ 1 ];
|
|
1597
|
+
const v2 = vertices[ 2 ];
|
|
1435
1598
|
|
|
1436
|
-
|
|
1599
|
+
_tempVec0.subVectors( v1, v0 );
|
|
1437
1600
|
|
|
1438
|
-
|
|
1439
|
-
// Changes to the backface culling state
|
|
1440
|
-
while ( ! lp.isAtTheEnd() ) {
|
|
1601
|
+
_tempVec1.subVectors( v2, v1 );
|
|
1441
1602
|
|
|
1442
|
-
|
|
1603
|
+
elem.faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize();
|
|
1443
1604
|
|
|
1444
|
-
|
|
1605
|
+
}
|
|
1445
1606
|
|
|
1446
|
-
|
|
1447
|
-
case 'NOCERTIFY':
|
|
1448
|
-
bfcCertified = token === 'CERTIFY';
|
|
1449
|
-
bfcCCW = true;
|
|
1450
|
-
break;
|
|
1607
|
+
let elemNormals = elem.normals;
|
|
1451
1608
|
|
|
1452
|
-
|
|
1453
|
-
case 'CCW':
|
|
1454
|
-
bfcCCW = token === 'CCW';
|
|
1455
|
-
break;
|
|
1609
|
+
if ( elemNormals.length === 4 ) {
|
|
1456
1610
|
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1611
|
+
quadArray[ 0 ] = elemNormals[ 0 ];
|
|
1612
|
+
quadArray[ 1 ] = elemNormals[ 1 ];
|
|
1613
|
+
quadArray[ 2 ] = elemNormals[ 2 ];
|
|
1614
|
+
quadArray[ 3 ] = elemNormals[ 0 ];
|
|
1615
|
+
quadArray[ 4 ] = elemNormals[ 2 ];
|
|
1616
|
+
quadArray[ 5 ] = elemNormals[ 3 ];
|
|
1617
|
+
elemNormals = quadArray;
|
|
1460
1618
|
|
|
1461
|
-
|
|
1462
|
-
case 'NOCLIP':
|
|
1463
|
-
bfcCull = token === 'CLIP';
|
|
1464
|
-
break;
|
|
1619
|
+
}
|
|
1465
1620
|
|
|
1466
|
-
|
|
1467
|
-
console.warn( 'THREE.LDrawLoader: BFC directive "' + token + '" is unknown.' );
|
|
1468
|
-
break;
|
|
1621
|
+
for ( let j = 0, l = elemNormals.length; j < l; j ++ ) {
|
|
1469
1622
|
|
|
1470
|
-
|
|
1623
|
+
// use face normal if a vertex normal is not provided
|
|
1624
|
+
let n = elem.faceNormal;
|
|
1471
1625
|
|
|
1472
|
-
|
|
1626
|
+
if ( elemNormals[ j ] ) {
|
|
1473
1627
|
|
|
1474
|
-
|
|
1628
|
+
n = elemNormals[ j ].norm;
|
|
1475
1629
|
|
|
1476
|
-
|
|
1477
|
-
startingConstructionStep = true;
|
|
1478
|
-
break;
|
|
1630
|
+
}
|
|
1479
1631
|
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1632
|
+
const index = offset + j * 3;
|
|
1633
|
+
normals[ index + 0 ] = n.x;
|
|
1634
|
+
normals[ index + 1 ] = n.y;
|
|
1635
|
+
normals[ index + 2 ] = n.z;
|
|
1483
1636
|
|
|
1484
|
-
|
|
1637
|
+
}
|
|
1485
1638
|
|
|
1486
|
-
|
|
1639
|
+
}
|
|
1487
1640
|
|
|
1488
|
-
|
|
1489
|
-
// Line type 1: Sub-object file
|
|
1641
|
+
if ( prevMaterial !== elem.colorCode ) {
|
|
1490
1642
|
|
|
1491
|
-
|
|
1492
|
-
material = parseColourCode( lp );
|
|
1493
|
-
const posX = parseFloat( lp.getToken() );
|
|
1494
|
-
const posY = parseFloat( lp.getToken() );
|
|
1495
|
-
const posZ = parseFloat( lp.getToken() );
|
|
1496
|
-
const m0 = parseFloat( lp.getToken() );
|
|
1497
|
-
const m1 = parseFloat( lp.getToken() );
|
|
1498
|
-
const m2 = parseFloat( lp.getToken() );
|
|
1499
|
-
const m3 = parseFloat( lp.getToken() );
|
|
1500
|
-
const m4 = parseFloat( lp.getToken() );
|
|
1501
|
-
const m5 = parseFloat( lp.getToken() );
|
|
1502
|
-
const m6 = parseFloat( lp.getToken() );
|
|
1503
|
-
const m7 = parseFloat( lp.getToken() );
|
|
1504
|
-
const m8 = parseFloat( lp.getToken() );
|
|
1505
|
-
const matrix = new THREE.Matrix4().set( m0, m1, m2, posX, m3, m4, m5, posY, m6, m7, m8, posZ, 0, 0, 0, 1 );
|
|
1506
|
-
let fileName = lp.getRemainingString().trim().replace( /\\/g, '/' );
|
|
1643
|
+
if ( prevMaterial !== null ) {
|
|
1507
1644
|
|
|
1508
|
-
|
|
1645
|
+
bufferGeometry.addGroup( index0, numGroupVerts, materials.length - 1 );
|
|
1509
1646
|
|
|
1510
|
-
|
|
1511
|
-
fileName = scope.fileMap[ fileName ];
|
|
1647
|
+
}
|
|
1512
1648
|
|
|
1513
|
-
|
|
1649
|
+
const material = elem.material;
|
|
1514
1650
|
|
|
1515
|
-
|
|
1516
|
-
if ( fileName.startsWith( 's/' ) ) {
|
|
1651
|
+
if ( material !== null ) {
|
|
1517
1652
|
|
|
1518
|
-
|
|
1653
|
+
if ( elementSize === 3 ) {
|
|
1519
1654
|
|
|
1520
|
-
|
|
1655
|
+
materials.push( material );
|
|
1521
1656
|
|
|
1522
|
-
|
|
1657
|
+
} else if ( elementSize === 2 ) {
|
|
1523
1658
|
|
|
1524
|
-
|
|
1659
|
+
if ( isConditionalSegments ) {
|
|
1660
|
+
|
|
1661
|
+
materials.push( material.userData.edgeMaterial.userData.conditionalEdgeMaterial );
|
|
1662
|
+
|
|
1663
|
+
} else {
|
|
1664
|
+
|
|
1665
|
+
materials.push( material.userData.edgeMaterial );
|
|
1525
1666
|
|
|
1526
1667
|
}
|
|
1527
1668
|
|
|
1528
|
-
|
|
1529
|
-
material: material,
|
|
1530
|
-
matrix: matrix,
|
|
1531
|
-
fileName: fileName,
|
|
1532
|
-
inverted: bfcInverted !== currentParseScope.inverted,
|
|
1533
|
-
startingConstructionStep: startingConstructionStep
|
|
1534
|
-
} );
|
|
1535
|
-
bfcInverted = false;
|
|
1536
|
-
break;
|
|
1537
|
-
// Line type 2: Line segment
|
|
1669
|
+
}
|
|
1538
1670
|
|
|
1539
|
-
|
|
1540
|
-
material = parseColourCode( lp, true );
|
|
1541
|
-
v0 = parseVector( lp );
|
|
1542
|
-
v1 = parseVector( lp );
|
|
1543
|
-
segment = {
|
|
1544
|
-
material: material.userData.edgeMaterial,
|
|
1545
|
-
colourCode: material.userData.code,
|
|
1546
|
-
v0: v0,
|
|
1547
|
-
v1: v1,
|
|
1548
|
-
vertices: [ v0, v1 ]
|
|
1549
|
-
};
|
|
1550
|
-
lineSegments.push( segment );
|
|
1551
|
-
break;
|
|
1552
|
-
// Line type 5: Conditional Line segment
|
|
1671
|
+
} else {
|
|
1553
1672
|
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1673
|
+
// If a material has not been made available yet then keep the color code string in the material array
|
|
1674
|
+
// to save the spot for the material once a parent scopes materials are being applied to the object.
|
|
1675
|
+
materials.push( elem.colorCode );
|
|
1676
|
+
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
prevMaterial = elem.colorCode;
|
|
1680
|
+
index0 = offset / 3;
|
|
1681
|
+
numGroupVerts = vertices.length;
|
|
1682
|
+
|
|
1683
|
+
} else {
|
|
1684
|
+
|
|
1685
|
+
numGroupVerts += vertices.length;
|
|
1686
|
+
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
offset += 3 * vertices.length;
|
|
1690
|
+
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
if ( numGroupVerts > 0 ) {
|
|
1694
|
+
|
|
1695
|
+
bufferGeometry.addGroup( index0, Infinity, materials.length - 1 );
|
|
1696
|
+
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
bufferGeometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
|
|
1700
|
+
|
|
1701
|
+
if ( normals !== null ) {
|
|
1702
|
+
|
|
1703
|
+
bufferGeometry.setAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
|
|
1704
|
+
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
let object3d = null;
|
|
1708
|
+
|
|
1709
|
+
if ( elementSize === 2 ) {
|
|
1710
|
+
|
|
1711
|
+
if ( isConditionalSegments ) {
|
|
1712
|
+
|
|
1713
|
+
object3d = new ConditionalLineSegments( bufferGeometry, materials.length === 1 ? materials[ 0 ] : materials );
|
|
1714
|
+
|
|
1715
|
+
} else {
|
|
1716
|
+
|
|
1717
|
+
object3d = new THREE.LineSegments( bufferGeometry, materials.length === 1 ? materials[ 0 ] : materials );
|
|
1718
|
+
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
} else if ( elementSize === 3 ) {
|
|
1722
|
+
|
|
1723
|
+
object3d = new THREE.Mesh( bufferGeometry, materials.length === 1 ? materials[ 0 ] : materials );
|
|
1724
|
+
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
if ( isConditionalSegments ) {
|
|
1728
|
+
|
|
1729
|
+
object3d.isConditionalLine = true;
|
|
1730
|
+
const controlArray0 = new Float32Array( elements.length * 3 * 2 );
|
|
1731
|
+
const controlArray1 = new Float32Array( elements.length * 3 * 2 );
|
|
1732
|
+
const directionArray = new Float32Array( elements.length * 3 * 2 );
|
|
1733
|
+
|
|
1734
|
+
for ( let i = 0, l = elements.length; i < l; i ++ ) {
|
|
1735
|
+
|
|
1736
|
+
const os = elements[ i ];
|
|
1737
|
+
const vertices = os.vertices;
|
|
1738
|
+
const controlPoints = os.controlPoints;
|
|
1739
|
+
const c0 = controlPoints[ 0 ];
|
|
1740
|
+
const c1 = controlPoints[ 1 ];
|
|
1741
|
+
const v0 = vertices[ 0 ];
|
|
1742
|
+
const v1 = vertices[ 1 ];
|
|
1743
|
+
const index = i * 3 * 2;
|
|
1744
|
+
controlArray0[ index + 0 ] = c0.x;
|
|
1745
|
+
controlArray0[ index + 1 ] = c0.y;
|
|
1746
|
+
controlArray0[ index + 2 ] = c0.z;
|
|
1747
|
+
controlArray0[ index + 3 ] = c0.x;
|
|
1748
|
+
controlArray0[ index + 4 ] = c0.y;
|
|
1749
|
+
controlArray0[ index + 5 ] = c0.z;
|
|
1750
|
+
controlArray1[ index + 0 ] = c1.x;
|
|
1751
|
+
controlArray1[ index + 1 ] = c1.y;
|
|
1752
|
+
controlArray1[ index + 2 ] = c1.z;
|
|
1753
|
+
controlArray1[ index + 3 ] = c1.x;
|
|
1754
|
+
controlArray1[ index + 4 ] = c1.y;
|
|
1755
|
+
controlArray1[ index + 5 ] = c1.z;
|
|
1756
|
+
directionArray[ index + 0 ] = v1.x - v0.x;
|
|
1757
|
+
directionArray[ index + 1 ] = v1.y - v0.y;
|
|
1758
|
+
directionArray[ index + 2 ] = v1.z - v0.z;
|
|
1759
|
+
directionArray[ index + 3 ] = v1.x - v0.x;
|
|
1760
|
+
directionArray[ index + 4 ] = v1.y - v0.y;
|
|
1761
|
+
directionArray[ index + 5 ] = v1.z - v0.z;
|
|
1762
|
+
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
bufferGeometry.setAttribute( 'control0', new THREE.BufferAttribute( controlArray0, 3, false ) );
|
|
1766
|
+
bufferGeometry.setAttribute( 'control1', new THREE.BufferAttribute( controlArray1, 3, false ) );
|
|
1767
|
+
bufferGeometry.setAttribute( 'direction', new THREE.BufferAttribute( directionArray, 3, false ) );
|
|
1768
|
+
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
return object3d;
|
|
1772
|
+
|
|
1773
|
+
} //
|
|
1774
|
+
|
|
1775
|
+
|
|
1776
|
+
class LDrawLoader extends THREE.Loader {
|
|
1777
|
+
|
|
1778
|
+
constructor( manager ) {
|
|
1779
|
+
|
|
1780
|
+
super( manager ); // Array of THREE.Material
|
|
1781
|
+
|
|
1782
|
+
this.materials = [];
|
|
1783
|
+
this.materialLibrary = {}; // This also allows to handle the embedded text files ("0 FILE" lines)
|
|
1784
|
+
|
|
1785
|
+
this.partsCache = new LDrawPartsGeometryCache( this ); // 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.
|
|
1786
|
+
|
|
1787
|
+
this.fileMap = {}; // Initializes the materials library with default materials
|
|
1788
|
+
|
|
1789
|
+
this.setMaterials( [] ); // If this flag is set to true the vertex normals will be smoothed.
|
|
1790
|
+
|
|
1791
|
+
this.smoothNormals = true; // The path to load parts from the LDraw parts library from.
|
|
1792
|
+
|
|
1793
|
+
this.partsLibraryPath = '';
|
|
1794
|
+
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
setPartsLibraryPath( path ) {
|
|
1798
|
+
|
|
1799
|
+
this.partsLibraryPath = path;
|
|
1800
|
+
return this;
|
|
1801
|
+
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
async preloadMaterials( url ) {
|
|
1805
|
+
|
|
1806
|
+
const fileLoader = new THREE.FileLoader( this.manager );
|
|
1807
|
+
fileLoader.setPath( this.path );
|
|
1808
|
+
fileLoader.setRequestHeader( this.requestHeader );
|
|
1809
|
+
fileLoader.setWithCredentials( this.withCredentials );
|
|
1810
|
+
const text = await fileLoader.loadAsync( url );
|
|
1811
|
+
const colorLineRegex = /^0 !COLOUR/;
|
|
1812
|
+
const lines = text.split( /[\n\r]/g );
|
|
1813
|
+
const materials = [];
|
|
1814
|
+
|
|
1815
|
+
for ( let i = 0, l = lines.length; i < l; i ++ ) {
|
|
1816
|
+
|
|
1817
|
+
const line = lines[ i ];
|
|
1818
|
+
|
|
1819
|
+
if ( colorLineRegex.test( line ) ) {
|
|
1820
|
+
|
|
1821
|
+
const directive = line.replace( colorLineRegex, '' );
|
|
1822
|
+
const material = this.parseColorMetaDirective( new LineParser( directive ) );
|
|
1823
|
+
materials.push( material );
|
|
1824
|
+
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
this.setMaterials( materials );
|
|
1830
|
+
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
load( url, onLoad, onProgress, onError ) {
|
|
1834
|
+
|
|
1835
|
+
const fileLoader = new THREE.FileLoader( this.manager );
|
|
1836
|
+
fileLoader.setPath( this.path );
|
|
1837
|
+
fileLoader.setRequestHeader( this.requestHeader );
|
|
1838
|
+
fileLoader.setWithCredentials( this.withCredentials );
|
|
1839
|
+
fileLoader.load( url, text => {
|
|
1840
|
+
|
|
1841
|
+
this.partsCache.parseModel( text, this.materialLibrary ).then( group => {
|
|
1842
|
+
|
|
1843
|
+
this.applyMaterialsToMesh( group, MAIN_COLOUR_CODE, this.materialLibrary, true );
|
|
1844
|
+
this.computeConstructionSteps( group );
|
|
1845
|
+
onLoad( group );
|
|
1846
|
+
|
|
1847
|
+
} ).catch( onError );
|
|
1848
|
+
|
|
1849
|
+
}, onProgress, onError );
|
|
1850
|
+
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
parse( text, onLoad ) {
|
|
1854
|
+
|
|
1855
|
+
this.partsCache.parseModel( text, this.materialLibrary ).then( group => {
|
|
1856
|
+
|
|
1857
|
+
this.computeConstructionSteps( group );
|
|
1858
|
+
onLoad( group );
|
|
1859
|
+
|
|
1860
|
+
} );
|
|
1861
|
+
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
setMaterials( materials ) {
|
|
1865
|
+
|
|
1866
|
+
this.materialLibrary = {};
|
|
1867
|
+
this.materials = [];
|
|
1868
|
+
|
|
1869
|
+
for ( let i = 0, l = materials.length; i < l; i ++ ) {
|
|
1870
|
+
|
|
1871
|
+
this.addMaterial( materials[ i ] );
|
|
1872
|
+
|
|
1873
|
+
} // Add default main triangle and line edge materials (used in pieces that can be colored with a main color)
|
|
1874
|
+
|
|
1875
|
+
|
|
1876
|
+
this.addMaterial( this.parseColorMetaDirective( new LineParser( 'Main_Colour CODE 16 VALUE #FF8080 EDGE #333333' ) ) );
|
|
1877
|
+
this.addMaterial( this.parseColorMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) ) );
|
|
1878
|
+
return this;
|
|
1879
|
+
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
setFileMap( fileMap ) {
|
|
1883
|
+
|
|
1884
|
+
this.fileMap = fileMap;
|
|
1885
|
+
return this;
|
|
1886
|
+
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
addMaterial( material ) {
|
|
1890
|
+
|
|
1891
|
+
// Adds a material to the material library which is on top of the parse scopes stack. And also to the materials array
|
|
1892
|
+
const matLib = this.materialLibrary;
|
|
1893
|
+
|
|
1894
|
+
if ( ! matLib[ material.userData.code ] ) {
|
|
1569
1895
|
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
inverted = currentParseScope.inverted;
|
|
1573
|
-
ccw = bfcCCW !== inverted;
|
|
1574
|
-
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1896
|
+
this.materials.push( material );
|
|
1897
|
+
matLib[ material.userData.code ] = material;
|
|
1575
1898
|
|
|
1576
|
-
|
|
1899
|
+
}
|
|
1577
1900
|
|
|
1578
|
-
|
|
1579
|
-
v1 = parseVector( lp );
|
|
1580
|
-
v2 = parseVector( lp );
|
|
1901
|
+
return this;
|
|
1581
1902
|
|
|
1582
|
-
|
|
1903
|
+
}
|
|
1583
1904
|
|
|
1584
|
-
|
|
1585
|
-
v1 = parseVector( lp );
|
|
1586
|
-
v0 = parseVector( lp );
|
|
1905
|
+
getMaterial( colorCode ) {
|
|
1587
1906
|
|
|
1588
|
-
|
|
1907
|
+
if ( colorCode.startsWith( '0x2' ) ) {
|
|
1589
1908
|
|
|
1590
|
-
|
|
1909
|
+
// Special 'direct' material value (RGB color)
|
|
1910
|
+
const color = colorCode.substring( 3 );
|
|
1911
|
+
return this.parseColorMetaDirective( new LineParser( 'Direct_Color_' + color + ' CODE -1 VALUE #' + color + ' EDGE #' + color + '' ) );
|
|
1591
1912
|
|
|
1592
|
-
|
|
1913
|
+
}
|
|
1593
1914
|
|
|
1594
|
-
|
|
1595
|
-
faces.push( {
|
|
1596
|
-
material: material,
|
|
1597
|
-
colourCode: material.userData.code,
|
|
1598
|
-
faceNormal: faceNormal,
|
|
1599
|
-
vertices: [ v0, v1, v2 ],
|
|
1600
|
-
normals: [ null, null, null ]
|
|
1601
|
-
} );
|
|
1602
|
-
currentParseScope.totalFaces ++;
|
|
1915
|
+
return this.materialLibrary[ colorCode ] || null;
|
|
1603
1916
|
|
|
1604
|
-
|
|
1917
|
+
} // Applies the appropriate materials to a prebuilt hierarchy of geometry. Assumes that color codes are present
|
|
1918
|
+
// in the material array if they need to be filled in.
|
|
1605
1919
|
|
|
1606
|
-
faces.push( {
|
|
1607
|
-
material: material,
|
|
1608
|
-
colourCode: material.userData.code,
|
|
1609
|
-
faceNormal: faceNormal,
|
|
1610
|
-
vertices: [ v2, v1, v0 ],
|
|
1611
|
-
normals: [ null, null, null ]
|
|
1612
|
-
} );
|
|
1613
|
-
currentParseScope.totalFaces ++;
|
|
1614
1920
|
|
|
1615
|
-
|
|
1921
|
+
applyMaterialsToMesh( group, parentColorCode, materialHierarchy, finalMaterialPass = false ) {
|
|
1616
1922
|
|
|
1617
|
-
|
|
1618
|
-
|
|
1923
|
+
// find any missing materials as indicated by a color code string and replace it with a material from the current material lib
|
|
1924
|
+
const loader = this;
|
|
1925
|
+
const parentIsPassthrough = parentColorCode === MAIN_COLOUR_CODE;
|
|
1926
|
+
group.traverse( c => {
|
|
1619
1927
|
|
|
1620
|
-
|
|
1621
|
-
material = parseColourCode( lp );
|
|
1622
|
-
inverted = currentParseScope.inverted;
|
|
1623
|
-
ccw = bfcCCW !== inverted;
|
|
1624
|
-
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1928
|
+
if ( c.isMesh || c.isLineSegments ) {
|
|
1625
1929
|
|
|
1626
|
-
|
|
1930
|
+
if ( Array.isArray( c.material ) ) {
|
|
1627
1931
|
|
|
1628
|
-
|
|
1629
|
-
v1 = parseVector( lp );
|
|
1630
|
-
v2 = parseVector( lp );
|
|
1631
|
-
v3 = parseVector( lp );
|
|
1932
|
+
for ( let i = 0, l = c.material.length; i < l; i ++ ) {
|
|
1632
1933
|
|
|
1633
|
-
|
|
1934
|
+
if ( ! c.material[ i ].isMaterial ) {
|
|
1634
1935
|
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
v0 = parseVector( lp );
|
|
1936
|
+
c.material[ i ] = getMaterial( c, c.material[ i ] );
|
|
1937
|
+
|
|
1938
|
+
}
|
|
1639
1939
|
|
|
1640
1940
|
}
|
|
1641
1941
|
|
|
1642
|
-
|
|
1942
|
+
} else if ( ! c.material.isMaterial ) {
|
|
1643
1943
|
|
|
1644
|
-
|
|
1944
|
+
c.material = getMaterial( c, c.material );
|
|
1645
1945
|
|
|
1646
|
-
|
|
1647
|
-
// account for the doubling of vertices later when smoothing normals.
|
|
1946
|
+
}
|
|
1648
1947
|
|
|
1649
|
-
|
|
1650
|
-
material: material,
|
|
1651
|
-
colourCode: material.userData.code,
|
|
1652
|
-
faceNormal: faceNormal,
|
|
1653
|
-
vertices: [ v0, v1, v2, v3 ],
|
|
1654
|
-
normals: [ null, null, null, null ]
|
|
1655
|
-
} );
|
|
1656
|
-
currentParseScope.totalFaces += 2;
|
|
1948
|
+
}
|
|
1657
1949
|
|
|
1658
|
-
|
|
1950
|
+
} ); // Returns the appropriate material for the object (line or face) given color code. If the code is "pass through"
|
|
1951
|
+
// (24 for lines, 16 for edges) then the pass through color code is used. If that is also pass through then it's
|
|
1952
|
+
// simply returned for the subsequent material application.
|
|
1659
1953
|
|
|
1660
|
-
|
|
1661
|
-
material: material,
|
|
1662
|
-
colourCode: material.userData.code,
|
|
1663
|
-
faceNormal: faceNormal,
|
|
1664
|
-
vertices: [ v3, v2, v1, v0 ],
|
|
1665
|
-
normals: [ null, null, null, null ]
|
|
1666
|
-
} );
|
|
1667
|
-
currentParseScope.totalFaces += 2;
|
|
1954
|
+
function getMaterial( c, colorCode ) {
|
|
1668
1955
|
|
|
1669
|
-
|
|
1956
|
+
// if our parent is a passthrough color code and we don't have the current material color available then
|
|
1957
|
+
// return early.
|
|
1958
|
+
if ( parentIsPassthrough && ! ( colorCode in materialHierarchy ) && ! finalMaterialPass ) {
|
|
1670
1959
|
|
|
1671
|
-
|
|
1960
|
+
return colorCode;
|
|
1672
1961
|
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
const forEdge = c.isLineSegments || c.isConditionalLine;
|
|
1965
|
+
const isPassthrough = ! forEdge && colorCode === MAIN_COLOUR_CODE || forEdge && colorCode === MAIN_EDGE_COLOUR_CODE;
|
|
1966
|
+
|
|
1967
|
+
if ( isPassthrough ) {
|
|
1968
|
+
|
|
1969
|
+
colorCode = parentColorCode;
|
|
1676
1970
|
|
|
1677
1971
|
}
|
|
1678
1972
|
|
|
1679
|
-
|
|
1973
|
+
let material = null;
|
|
1680
1974
|
|
|
1681
|
-
|
|
1975
|
+
if ( colorCode in materialHierarchy ) {
|
|
1682
1976
|
|
|
1683
|
-
|
|
1977
|
+
material = materialHierarchy[ colorCode ];
|
|
1684
1978
|
|
|
1685
|
-
|
|
1979
|
+
} else if ( finalMaterialPass ) {
|
|
1686
1980
|
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
currentParseScope.numSubobjects = subobjects.length;
|
|
1691
|
-
currentParseScope.subobjectIndex = 0;
|
|
1692
|
-
const isRoot = ! parentParseScope.isFromParse;
|
|
1981
|
+
// see if we can get the final material from from the "getMaterial" function which will attempt to
|
|
1982
|
+
// parse the "direct" colors
|
|
1983
|
+
material = loader.getMaterial( colorCode );
|
|
1693
1984
|
|
|
1694
|
-
|
|
1985
|
+
if ( material === null ) {
|
|
1695
1986
|
|
|
1696
|
-
|
|
1697
|
-
|
|
1987
|
+
// otherwise throw an error if this is final opportunity to set the material
|
|
1988
|
+
throw new Error( `LDrawLoader: Material properties for code ${colorCode} not available.` );
|
|
1698
1989
|
|
|
1699
|
-
|
|
1990
|
+
}
|
|
1700
1991
|
|
|
1701
|
-
|
|
1992
|
+
} else {
|
|
1702
1993
|
|
|
1703
|
-
|
|
1994
|
+
return colorCode;
|
|
1704
1995
|
|
|
1705
|
-
|
|
1706
|
-
let stepNumber = 0;
|
|
1707
|
-
model.traverse( c => {
|
|
1996
|
+
}
|
|
1708
1997
|
|
|
1709
|
-
if ( c.
|
|
1998
|
+
if ( c.isLineSegments ) {
|
|
1710
1999
|
|
|
1711
|
-
|
|
2000
|
+
material = material.userData.edgeMaterial;
|
|
1712
2001
|
|
|
1713
|
-
|
|
2002
|
+
if ( c.isConditionalLine ) {
|
|
1714
2003
|
|
|
1715
|
-
|
|
2004
|
+
material = material.userData.conditionalEdgeMaterial;
|
|
1716
2005
|
|
|
1717
|
-
|
|
2006
|
+
}
|
|
1718
2007
|
|
|
1719
2008
|
}
|
|
1720
2009
|
|
|
1721
|
-
|
|
1722
|
-
|
|
2010
|
+
return material;
|
|
2011
|
+
|
|
2012
|
+
}
|
|
1723
2013
|
|
|
1724
2014
|
}
|
|
1725
2015
|
|
|
1726
|
-
|
|
2016
|
+
getMainMaterial() {
|
|
1727
2017
|
|
|
1728
|
-
|
|
1729
|
-
if ( subobjectParseScope === null ) {
|
|
2018
|
+
return this.getMaterial( MAIN_COLOUR_CODE );
|
|
1730
2019
|
|
|
1731
|
-
|
|
2020
|
+
}
|
|
1732
2021
|
|
|
1733
|
-
|
|
2022
|
+
getMainEdgeMaterial() {
|
|
1734
2023
|
|
|
1735
|
-
const
|
|
1736
|
-
|
|
1737
|
-
// being added to a part)
|
|
2024
|
+
const mainMat = this.getMainMaterial();
|
|
2025
|
+
return mainMat && mainMat.userData ? mainMat.userData.edgeMaterial : null;
|
|
1738
2026
|
|
|
1739
|
-
|
|
2027
|
+
}
|
|
1740
2028
|
|
|
1741
|
-
|
|
2029
|
+
parseColorMetaDirective( lineParser ) {
|
|
1742
2030
|
|
|
1743
|
-
|
|
2031
|
+
// Parses a color definition and returns a THREE.Material
|
|
2032
|
+
let code = null; // Triangle and line colors
|
|
1744
2033
|
|
|
1745
|
-
|
|
2034
|
+
let color = 0xFF00FF;
|
|
2035
|
+
let edgeColor = 0xFF00FF; // Transparency
|
|
1746
2036
|
|
|
1747
|
-
|
|
2037
|
+
let alpha = 1;
|
|
2038
|
+
let isTransparent = false; // Self-illumination:
|
|
1748
2039
|
|
|
1749
|
-
|
|
2040
|
+
let luminance = 0;
|
|
2041
|
+
let finishType = FINISH_TYPE_DEFAULT;
|
|
2042
|
+
let edgeMaterial = null;
|
|
2043
|
+
const name = lineParser.getToken();
|
|
1750
2044
|
|
|
1751
|
-
|
|
2045
|
+
if ( ! name ) {
|
|
1752
2046
|
|
|
1753
|
-
|
|
2047
|
+
throw new Error( 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.' );
|
|
1754
2048
|
|
|
1755
|
-
|
|
2049
|
+
} // Parse tag tokens and their parameters
|
|
1756
2050
|
|
|
1757
|
-
}
|
|
1758
2051
|
|
|
1759
|
-
|
|
2052
|
+
let token = null;
|
|
1760
2053
|
|
|
1761
|
-
|
|
2054
|
+
while ( true ) {
|
|
1762
2055
|
|
|
1763
|
-
|
|
2056
|
+
token = lineParser.getToken();
|
|
1764
2057
|
|
|
1765
|
-
if (
|
|
2058
|
+
if ( ! token ) {
|
|
1766
2059
|
|
|
1767
|
-
|
|
2060
|
+
break;
|
|
1768
2061
|
|
|
1769
2062
|
}
|
|
1770
2063
|
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
objGroup.name = subobjectParseScope.fileName;
|
|
1774
|
-
objGroup.userData.category = subobjectParseScope.category;
|
|
1775
|
-
objGroup.userData.keywords = subobjectParseScope.keywords;
|
|
1776
|
-
subobjectParseScope.matrix.decompose( objGroup.position, objGroup.quaternion, objGroup.scale );
|
|
1777
|
-
parentParseScope.groupObject.add( objGroup );
|
|
2064
|
+
switch ( token.toUpperCase() ) {
|
|
1778
2065
|
|
|
1779
|
-
|
|
2066
|
+
case 'CODE':
|
|
2067
|
+
code = lineParser.getToken();
|
|
2068
|
+
break;
|
|
1780
2069
|
|
|
1781
|
-
|
|
2070
|
+
case 'VALUE':
|
|
2071
|
+
color = lineParser.getToken();
|
|
1782
2072
|
|
|
1783
|
-
|
|
1784
|
-
const parentLineSegments = parentParseScope.lineSegments;
|
|
1785
|
-
const parentConditionalSegments = parentParseScope.conditionalSegments;
|
|
1786
|
-
const parentFaces = parentParseScope.faces;
|
|
1787
|
-
const lineSegments = subobjectParseScope.lineSegments;
|
|
1788
|
-
const conditionalSegments = subobjectParseScope.conditionalSegments;
|
|
1789
|
-
const faces = subobjectParseScope.faces;
|
|
2073
|
+
if ( color.startsWith( '0x' ) ) {
|
|
1790
2074
|
|
|
1791
|
-
|
|
2075
|
+
color = '#' + color.substring( 2 );
|
|
1792
2076
|
|
|
1793
|
-
|
|
2077
|
+
} else if ( ! color.startsWith( '#' ) ) {
|
|
1794
2078
|
|
|
1795
|
-
|
|
2079
|
+
throw new Error( 'LDrawLoader: Invalid color while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
1796
2080
|
|
|
1797
|
-
|
|
1798
|
-
vertices[ 0 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1799
|
-
vertices[ 1 ].applyMatrix4( subobjectParseScope.matrix );
|
|
2081
|
+
}
|
|
1800
2082
|
|
|
1801
|
-
|
|
2083
|
+
break;
|
|
1802
2084
|
|
|
1803
|
-
|
|
2085
|
+
case 'EDGE':
|
|
2086
|
+
edgeColor = lineParser.getToken();
|
|
1804
2087
|
|
|
1805
|
-
|
|
2088
|
+
if ( edgeColor.startsWith( '0x' ) ) {
|
|
1806
2089
|
|
|
1807
|
-
|
|
2090
|
+
edgeColor = '#' + edgeColor.substring( 2 );
|
|
1808
2091
|
|
|
1809
|
-
|
|
2092
|
+
} else if ( ! edgeColor.startsWith( '#' ) ) {
|
|
1810
2093
|
|
|
1811
|
-
|
|
2094
|
+
// Try to see if edge color is a color code
|
|
2095
|
+
edgeMaterial = this.getMaterial( edgeColor );
|
|
1812
2096
|
|
|
1813
|
-
|
|
1814
|
-
const controlPoints = os.controlPoints;
|
|
1815
|
-
vertices[ 0 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1816
|
-
vertices[ 1 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1817
|
-
controlPoints[ 0 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1818
|
-
controlPoints[ 1 ].applyMatrix4( subobjectParseScope.matrix );
|
|
2097
|
+
if ( ! edgeMaterial ) {
|
|
1819
2098
|
|
|
1820
|
-
|
|
2099
|
+
throw new Error( 'LDrawLoader: Invalid edge color while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
1821
2100
|
|
|
1822
|
-
|
|
2101
|
+
} // Get the edge material for this triangle material
|
|
1823
2102
|
|
|
1824
|
-
}
|
|
1825
2103
|
|
|
1826
|
-
|
|
2104
|
+
edgeMaterial = edgeMaterial.userData.edgeMaterial;
|
|
1827
2105
|
|
|
1828
|
-
|
|
2106
|
+
}
|
|
1829
2107
|
|
|
1830
|
-
|
|
2108
|
+
break;
|
|
1831
2109
|
|
|
1832
|
-
|
|
2110
|
+
case 'ALPHA':
|
|
2111
|
+
alpha = parseInt( lineParser.getToken() );
|
|
1833
2112
|
|
|
1834
|
-
|
|
2113
|
+
if ( isNaN( alpha ) ) {
|
|
1835
2114
|
|
|
1836
|
-
|
|
2115
|
+
throw new Error( 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.' );
|
|
1837
2116
|
|
|
1838
2117
|
}
|
|
1839
2118
|
|
|
1840
|
-
|
|
2119
|
+
alpha = Math.max( 0, Math.min( 1, alpha / 255 ) );
|
|
2120
|
+
|
|
2121
|
+
if ( alpha < 1 ) {
|
|
1841
2122
|
|
|
1842
|
-
|
|
2123
|
+
isTransparent = true;
|
|
1843
2124
|
|
|
1844
|
-
|
|
2125
|
+
}
|
|
1845
2126
|
|
|
1846
|
-
|
|
2127
|
+
break;
|
|
1847
2128
|
|
|
1848
|
-
|
|
2129
|
+
case 'LUMINANCE':
|
|
2130
|
+
luminance = parseInt( lineParser.getToken() );
|
|
1849
2131
|
|
|
1850
|
-
|
|
2132
|
+
if ( isNaN( luminance ) ) {
|
|
1851
2133
|
|
|
1852
|
-
|
|
2134
|
+
throw new Error( 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.' );
|
|
1853
2135
|
|
|
1854
|
-
|
|
2136
|
+
}
|
|
1855
2137
|
|
|
1856
|
-
|
|
2138
|
+
luminance = Math.max( 0, Math.min( 1, luminance / 255 ) );
|
|
2139
|
+
break;
|
|
1857
2140
|
|
|
1858
|
-
|
|
2141
|
+
case 'CHROME':
|
|
2142
|
+
finishType = FINISH_TYPE_CHROME;
|
|
2143
|
+
break;
|
|
1859
2144
|
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
const parentParseScope = parseScope.parentScope; // Set current matrix
|
|
2145
|
+
case 'PEARLESCENT':
|
|
2146
|
+
finishType = FINISH_TYPE_PEARLESCENT;
|
|
2147
|
+
break;
|
|
1864
2148
|
|
|
1865
|
-
|
|
2149
|
+
case 'RUBBER':
|
|
2150
|
+
finishType = FINISH_TYPE_RUBBER;
|
|
2151
|
+
break;
|
|
1866
2152
|
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
parseScope.startingConstructionStep = subobject.startingConstructionStep;
|
|
1871
|
-
parseScope.mainColourCode = subobject.material.userData.code;
|
|
1872
|
-
parseScope.mainEdgeColourCode = subobject.material.userData.edgeMaterial.userData.code;
|
|
1873
|
-
parseScope.fileName = subobject.fileName;
|
|
2153
|
+
case 'MATTE_METALLIC':
|
|
2154
|
+
finishType = FINISH_TYPE_MATTE_METALLIC;
|
|
2155
|
+
break;
|
|
1874
2156
|
|
|
1875
|
-
|
|
2157
|
+
case 'METAL':
|
|
2158
|
+
finishType = FINISH_TYPE_METAL;
|
|
2159
|
+
break;
|
|
1876
2160
|
|
|
2161
|
+
case 'MATERIAL':
|
|
2162
|
+
// Not implemented
|
|
2163
|
+
lineParser.setToEnd();
|
|
2164
|
+
break;
|
|
1877
2165
|
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
const promises = [];
|
|
2166
|
+
default:
|
|
2167
|
+
throw new Error( 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
1881
2168
|
|
|
1882
|
-
|
|
2169
|
+
}
|
|
1883
2170
|
|
|
1884
|
-
|
|
2171
|
+
}
|
|
1885
2172
|
|
|
1886
|
-
|
|
1887
|
-
// in order so all the assembly instructions are correct
|
|
2173
|
+
let material = null;
|
|
1888
2174
|
|
|
2175
|
+
switch ( finishType ) {
|
|
1889
2176
|
|
|
1890
|
-
|
|
2177
|
+
case FINISH_TYPE_DEFAULT:
|
|
2178
|
+
material = new THREE.MeshStandardMaterial( {
|
|
2179
|
+
color: color,
|
|
2180
|
+
roughness: 0.3,
|
|
2181
|
+
metalness: 0
|
|
2182
|
+
} );
|
|
2183
|
+
break;
|
|
1891
2184
|
|
|
1892
|
-
|
|
2185
|
+
case FINISH_TYPE_PEARLESCENT:
|
|
2186
|
+
// Try to imitate pearlescency by making the surface glossy
|
|
2187
|
+
material = new THREE.MeshStandardMaterial( {
|
|
2188
|
+
color: color,
|
|
2189
|
+
roughness: 0.3,
|
|
2190
|
+
metalness: 0.25
|
|
2191
|
+
} );
|
|
2192
|
+
break;
|
|
1893
2193
|
|
|
1894
|
-
|
|
2194
|
+
case FINISH_TYPE_CHROME:
|
|
2195
|
+
// Mirror finish surface
|
|
2196
|
+
material = new THREE.MeshStandardMaterial( {
|
|
2197
|
+
color: color,
|
|
2198
|
+
roughness: 0,
|
|
2199
|
+
metalness: 1
|
|
2200
|
+
} );
|
|
2201
|
+
break;
|
|
1895
2202
|
|
|
1896
|
-
|
|
2203
|
+
case FINISH_TYPE_RUBBER:
|
|
2204
|
+
// Rubber finish
|
|
2205
|
+
material = new THREE.MeshStandardMaterial( {
|
|
2206
|
+
color: color,
|
|
2207
|
+
roughness: 0.9,
|
|
2208
|
+
metalness: 0
|
|
2209
|
+
} );
|
|
2210
|
+
break;
|
|
1897
2211
|
|
|
2212
|
+
case FINISH_TYPE_MATTE_METALLIC:
|
|
2213
|
+
// Brushed metal finish
|
|
2214
|
+
material = new THREE.MeshStandardMaterial( {
|
|
2215
|
+
color: color,
|
|
2216
|
+
roughness: 0.8,
|
|
2217
|
+
metalness: 0.4
|
|
2218
|
+
} );
|
|
2219
|
+
break;
|
|
1898
2220
|
|
|
1899
|
-
|
|
2221
|
+
case FINISH_TYPE_METAL:
|
|
2222
|
+
// Average metal finish
|
|
2223
|
+
material = new THREE.MeshStandardMaterial( {
|
|
2224
|
+
color: color,
|
|
2225
|
+
roughness: 0.2,
|
|
2226
|
+
metalness: 0.85
|
|
2227
|
+
} );
|
|
2228
|
+
break;
|
|
1900
2229
|
|
|
1901
|
-
|
|
1902
|
-
|
|
2230
|
+
default:
|
|
2231
|
+
// Should not happen
|
|
2232
|
+
break;
|
|
1903
2233
|
|
|
1904
2234
|
}
|
|
1905
2235
|
|
|
1906
|
-
|
|
2236
|
+
material.transparent = isTransparent;
|
|
2237
|
+
material.premultipliedAlpha = true;
|
|
2238
|
+
material.opacity = alpha;
|
|
2239
|
+
material.depthWrite = ! isTransparent;
|
|
2240
|
+
material.color.convertSRGBToLinear();
|
|
2241
|
+
material.polygonOffset = true;
|
|
2242
|
+
material.polygonOffsetFactor = 1;
|
|
1907
2243
|
|
|
1908
|
-
|
|
2244
|
+
if ( luminance !== 0 ) {
|
|
1909
2245
|
|
|
1910
|
-
|
|
2246
|
+
material.emissive.set( material.color ).multiplyScalar( luminance );
|
|
1911
2247
|
|
|
1912
|
-
|
|
2248
|
+
}
|
|
1913
2249
|
|
|
1914
|
-
|
|
2250
|
+
if ( ! edgeMaterial ) {
|
|
1915
2251
|
|
|
1916
|
-
|
|
1917
|
-
|
|
2252
|
+
// This is the material used for edges
|
|
2253
|
+
edgeMaterial = new THREE.LineBasicMaterial( {
|
|
2254
|
+
color: edgeColor,
|
|
2255
|
+
transparent: isTransparent,
|
|
2256
|
+
opacity: alpha,
|
|
2257
|
+
depthWrite: ! isTransparent
|
|
2258
|
+
} );
|
|
2259
|
+
edgeMaterial.userData.code = code;
|
|
2260
|
+
edgeMaterial.name = name + ' - Edge';
|
|
2261
|
+
edgeMaterial.color.convertSRGBToLinear(); // This is the material used for conditional edges
|
|
1918
2262
|
|
|
2263
|
+
edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial( {
|
|
2264
|
+
fog: true,
|
|
2265
|
+
transparent: isTransparent,
|
|
2266
|
+
depthWrite: ! isTransparent,
|
|
2267
|
+
color: edgeColor,
|
|
2268
|
+
opacity: alpha
|
|
1919
2269
|
} );
|
|
2270
|
+
edgeMaterial.userData.conditionalEdgeMaterial.color.convertSRGBToLinear();
|
|
1920
2271
|
|
|
1921
2272
|
}
|
|
1922
2273
|
|
|
2274
|
+
material.userData.code = code;
|
|
2275
|
+
material.name = name;
|
|
2276
|
+
material.userData.edgeMaterial = edgeMaterial;
|
|
2277
|
+
this.addMaterial( material );
|
|
2278
|
+
return material;
|
|
2279
|
+
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
computeConstructionSteps( model ) {
|
|
2283
|
+
|
|
2284
|
+
// Sets userdata.constructionStep number in THREE.Group objects and userData.numConstructionSteps number in the root THREE.Group object.
|
|
2285
|
+
let stepNumber = 0;
|
|
2286
|
+
model.traverse( c => {
|
|
2287
|
+
|
|
2288
|
+
if ( c.isGroup ) {
|
|
2289
|
+
|
|
2290
|
+
if ( c.userData.startingConstructionStep ) {
|
|
2291
|
+
|
|
2292
|
+
stepNumber ++;
|
|
2293
|
+
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
c.userData.constructionStep = stepNumber;
|
|
2297
|
+
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
} );
|
|
2301
|
+
model.userData.numConstructionSteps = stepNumber + 1;
|
|
2302
|
+
|
|
1923
2303
|
}
|
|
1924
2304
|
|
|
1925
2305
|
}
|