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
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
ShaderMaterial,
|
|
14
14
|
UniformsLib,
|
|
15
15
|
UniformsUtils,
|
|
16
|
-
Vector3
|
|
16
|
+
Vector3,
|
|
17
|
+
Ray
|
|
17
18
|
} from 'three';
|
|
18
19
|
|
|
19
20
|
// Special surface finish tag types.
|
|
@@ -35,6 +36,9 @@ const FILE_LOCATION_TRY_RELATIVE = 4;
|
|
|
35
36
|
const FILE_LOCATION_TRY_ABSOLUTE = 5;
|
|
36
37
|
const FILE_LOCATION_NOT_FOUND = 6;
|
|
37
38
|
|
|
39
|
+
const MAIN_COLOUR_CODE = '16';
|
|
40
|
+
const MAIN_EDGE_COLOUR_CODE = '24';
|
|
41
|
+
|
|
38
42
|
const _tempVec0 = new Vector3();
|
|
39
43
|
const _tempVec1 = new Vector3();
|
|
40
44
|
|
|
@@ -167,16 +171,56 @@ class LDrawConditionalLineMaterial extends ShaderMaterial {
|
|
|
167
171
|
|
|
168
172
|
}
|
|
169
173
|
|
|
170
|
-
|
|
174
|
+
class ConditionalLineSegments extends LineSegments {
|
|
175
|
+
|
|
176
|
+
constructor( geometry, material ) {
|
|
177
|
+
|
|
178
|
+
super( geometry, material );
|
|
179
|
+
this.isConditionalLine = true;
|
|
180
|
+
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function generateFaceNormals( faces ) {
|
|
186
|
+
|
|
187
|
+
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
188
|
+
|
|
189
|
+
const face = faces[ i ];
|
|
190
|
+
const vertices = face.vertices;
|
|
191
|
+
const v0 = vertices[ 0 ];
|
|
192
|
+
const v1 = vertices[ 1 ];
|
|
193
|
+
const v2 = vertices[ 2 ];
|
|
194
|
+
|
|
195
|
+
_tempVec0.subVectors( v1, v0 );
|
|
196
|
+
_tempVec1.subVectors( v2, v1 );
|
|
197
|
+
face.faceNormal = new Vector3()
|
|
198
|
+
.crossVectors( _tempVec0, _tempVec1 )
|
|
199
|
+
.normalize();
|
|
200
|
+
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const _ray = new Ray();
|
|
206
|
+
function smoothNormals( faces, lineSegments, checkSubSegments = false ) {
|
|
207
|
+
|
|
208
|
+
// NOTE: 1e2 is pretty coarse but was chosen to quantize the resulting value because
|
|
209
|
+
// it allows edges to be smoothed as expected (see minifig arms).
|
|
210
|
+
// --
|
|
211
|
+
// And the vector values are initialize multiplied by 1 + 1e-10 to account for floating
|
|
212
|
+
// point errors on vertices along quantization boundaries. Ie after matrix multiplication
|
|
213
|
+
// vertices that should be merged might be set to "1.7" and "1.6999..." meaning they won't
|
|
214
|
+
// get merged. This added epsilon attempts to push these error values to the same quantized
|
|
215
|
+
// value for the sake of hashing. See "AT-ST mini" dishes. See mrdoob/three#23169.
|
|
171
216
|
|
|
217
|
+
const hashMultiplier = ( 1 + 1e-10 ) * 1e2;
|
|
172
218
|
function hashVertex( v ) {
|
|
173
219
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const y = ~ ~ ( v.y * 1e2 );
|
|
179
|
-
const z = ~ ~ ( v.z * 1e2 );
|
|
220
|
+
const x = ~ ~ ( v.x * hashMultiplier );
|
|
221
|
+
const y = ~ ~ ( v.y * hashMultiplier );
|
|
222
|
+
const z = ~ ~ ( v.z * hashMultiplier );
|
|
223
|
+
|
|
180
224
|
return `${ x },${ y },${ z }`;
|
|
181
225
|
|
|
182
226
|
}
|
|
@@ -187,7 +231,27 @@ function smoothNormals( faces, lineSegments ) {
|
|
|
187
231
|
|
|
188
232
|
}
|
|
189
233
|
|
|
234
|
+
// converts the two vertices to a ray with a normalized direction and origin of 0, 0, 0 projected
|
|
235
|
+
// onto the original line.
|
|
236
|
+
function toNormalizedRay( v0, v1, targetRay ) {
|
|
237
|
+
|
|
238
|
+
targetRay.direction.subVectors( v1, v0 ).normalize();
|
|
239
|
+
|
|
240
|
+
const scalar = v0.dot( targetRay.direction );
|
|
241
|
+
targetRay.origin.copy( v0 ).addScaledVector( targetRay.direction, - scalar );
|
|
242
|
+
|
|
243
|
+
return targetRay;
|
|
244
|
+
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function hashRay( ray ) {
|
|
248
|
+
|
|
249
|
+
return hashEdge( ray.origin, ray.direction );
|
|
250
|
+
|
|
251
|
+
}
|
|
252
|
+
|
|
190
253
|
const hardEdges = new Set();
|
|
254
|
+
const hardEdgeRays = new Map();
|
|
191
255
|
const halfEdgeList = {};
|
|
192
256
|
const normals = [];
|
|
193
257
|
|
|
@@ -201,6 +265,43 @@ function smoothNormals( faces, lineSegments ) {
|
|
|
201
265
|
hardEdges.add( hashEdge( v0, v1 ) );
|
|
202
266
|
hardEdges.add( hashEdge( v1, v0 ) );
|
|
203
267
|
|
|
268
|
+
// only generate the hard edge ray map if we're checking subsegments because it's more expensive to check
|
|
269
|
+
// and requires more memory.
|
|
270
|
+
if ( checkSubSegments ) {
|
|
271
|
+
|
|
272
|
+
// add both ray directions to the map
|
|
273
|
+
const ray = toNormalizedRay( v0, v1, new Ray() );
|
|
274
|
+
const rh1 = hashRay( ray );
|
|
275
|
+
if ( ! hardEdgeRays.has( rh1 ) ) {
|
|
276
|
+
|
|
277
|
+
toNormalizedRay( v1, v0, ray );
|
|
278
|
+
const rh2 = hashRay( ray );
|
|
279
|
+
|
|
280
|
+
const info = {
|
|
281
|
+
ray,
|
|
282
|
+
distances: [],
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
hardEdgeRays.set( rh1, info );
|
|
286
|
+
hardEdgeRays.set( rh2, info );
|
|
287
|
+
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// store both segments ends in min, max order in the distances array to check if a face edge is a
|
|
291
|
+
// subsegment later.
|
|
292
|
+
const info = hardEdgeRays.get( rh1 );
|
|
293
|
+
let d0 = info.ray.direction.dot( v0 );
|
|
294
|
+
let d1 = info.ray.direction.dot( v1 );
|
|
295
|
+
if ( d0 > d1 ) {
|
|
296
|
+
|
|
297
|
+
[ d0, d1 ] = [ d1, d0 ];
|
|
298
|
+
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
info.distances.push( d0, d1 );
|
|
302
|
+
|
|
303
|
+
}
|
|
304
|
+
|
|
204
305
|
}
|
|
205
306
|
|
|
206
307
|
// track the half edges associated with each triangle
|
|
@@ -218,7 +319,53 @@ function smoothNormals( faces, lineSegments ) {
|
|
|
218
319
|
const hash = hashEdge( v0, v1 );
|
|
219
320
|
|
|
220
321
|
// don't add the triangle if the edge is supposed to be hard
|
|
221
|
-
if ( hardEdges.has( hash ) )
|
|
322
|
+
if ( hardEdges.has( hash ) ) {
|
|
323
|
+
|
|
324
|
+
continue;
|
|
325
|
+
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// if checking subsegments then check to see if this edge lies on a hard edge ray and whether its within any ray bounds
|
|
329
|
+
if ( checkSubSegments ) {
|
|
330
|
+
|
|
331
|
+
toNormalizedRay( v0, v1, _ray );
|
|
332
|
+
|
|
333
|
+
const rayHash = hashRay( _ray );
|
|
334
|
+
if ( hardEdgeRays.has( rayHash ) ) {
|
|
335
|
+
|
|
336
|
+
const info = hardEdgeRays.get( rayHash );
|
|
337
|
+
const { ray, distances } = info;
|
|
338
|
+
let d0 = ray.direction.dot( v0 );
|
|
339
|
+
let d1 = ray.direction.dot( v1 );
|
|
340
|
+
|
|
341
|
+
if ( d0 > d1 ) {
|
|
342
|
+
|
|
343
|
+
[ d0, d1 ] = [ d1, d0 ];
|
|
344
|
+
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// return early if the face edge is found to be a subsegment of a line edge meaning the edge will have "hard" normals
|
|
348
|
+
let found = false;
|
|
349
|
+
for ( let i = 0, l = distances.length; i < l; i += 2 ) {
|
|
350
|
+
|
|
351
|
+
if ( d0 >= distances[ i ] && d1 <= distances[ i + 1 ] ) {
|
|
352
|
+
|
|
353
|
+
found = true;
|
|
354
|
+
break;
|
|
355
|
+
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if ( found ) {
|
|
361
|
+
|
|
362
|
+
continue;
|
|
363
|
+
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
}
|
|
222
369
|
|
|
223
370
|
const info = {
|
|
224
371
|
index: index,
|
|
@@ -389,13 +536,7 @@ function smoothNormals( faces, lineSegments ) {
|
|
|
389
536
|
|
|
390
537
|
function isPartType( type ) {
|
|
391
538
|
|
|
392
|
-
return type === 'Part';
|
|
393
|
-
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
function isModelType( type ) {
|
|
397
|
-
|
|
398
|
-
return type === 'Model' || type === 'Unofficial_Model';
|
|
539
|
+
return type === 'Part' || type === 'Unofficial_Part';
|
|
399
540
|
|
|
400
541
|
}
|
|
401
542
|
|
|
@@ -462,6 +603,12 @@ class LineParser {
|
|
|
462
603
|
|
|
463
604
|
}
|
|
464
605
|
|
|
606
|
+
getVector() {
|
|
607
|
+
|
|
608
|
+
return new Vector3( parseFloat( this.getToken() ), parseFloat( this.getToken() ), parseFloat( this.getToken() ) );
|
|
609
|
+
|
|
610
|
+
}
|
|
611
|
+
|
|
465
612
|
getRemainingString() {
|
|
466
613
|
|
|
467
614
|
return this.line.substring( this.currentCharIndex, this.lineLength );
|
|
@@ -488,1566 +635,1766 @@ class LineParser {
|
|
|
488
635
|
|
|
489
636
|
}
|
|
490
637
|
|
|
491
|
-
|
|
638
|
+
// Fetches and parses an intermediate representation of LDraw parts files.
|
|
639
|
+
class LDrawParsedCache {
|
|
492
640
|
|
|
493
641
|
constructor( loader ) {
|
|
494
642
|
|
|
495
|
-
this.cache = {};
|
|
496
643
|
this.loader = loader;
|
|
644
|
+
this._cache = {};
|
|
497
645
|
|
|
498
646
|
}
|
|
499
647
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
this.cache[ key.toLowerCase() ] = contents;
|
|
648
|
+
cloneResult( original ) {
|
|
503
649
|
|
|
504
|
-
|
|
650
|
+
const result = {};
|
|
505
651
|
|
|
506
|
-
|
|
652
|
+
// vertices are transformed and normals computed before being converted to geometry
|
|
653
|
+
// so these pieces must be cloned.
|
|
654
|
+
result.faces = original.faces.map( face => {
|
|
507
655
|
|
|
508
|
-
|
|
509
|
-
|
|
656
|
+
return {
|
|
657
|
+
colorCode: face.colorCode,
|
|
658
|
+
material: face.material,
|
|
659
|
+
vertices: face.vertices.map( v => v.clone() ),
|
|
660
|
+
normals: face.normals.map( () => null ),
|
|
661
|
+
faceNormal: null
|
|
662
|
+
};
|
|
510
663
|
|
|
511
|
-
|
|
664
|
+
} );
|
|
512
665
|
|
|
513
|
-
|
|
666
|
+
result.conditionalSegments = original.conditionalSegments.map( face => {
|
|
514
667
|
|
|
515
|
-
|
|
668
|
+
return {
|
|
669
|
+
colorCode: face.colorCode,
|
|
670
|
+
material: face.material,
|
|
671
|
+
vertices: face.vertices.map( v => v.clone() ),
|
|
672
|
+
controlPoints: face.controlPoints.map( v => v.clone() )
|
|
673
|
+
};
|
|
516
674
|
|
|
517
|
-
|
|
518
|
-
let locationState = FILE_LOCATION_AS_IS;
|
|
519
|
-
while ( locationState !== FILE_LOCATION_NOT_FOUND ) {
|
|
675
|
+
} );
|
|
520
676
|
|
|
521
|
-
|
|
522
|
-
switch ( locationState ) {
|
|
677
|
+
result.lineSegments = original.lineSegments.map( face => {
|
|
523
678
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
679
|
+
return {
|
|
680
|
+
colorCode: face.colorCode,
|
|
681
|
+
material: face.material,
|
|
682
|
+
vertices: face.vertices.map( v => v.clone() )
|
|
683
|
+
};
|
|
527
684
|
|
|
528
|
-
|
|
529
|
-
subobjectURL = 'parts/' + subobjectURL;
|
|
530
|
-
locationState = locationState + 1;
|
|
531
|
-
break;
|
|
685
|
+
} );
|
|
532
686
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
687
|
+
// none if this is subsequently modified
|
|
688
|
+
result.type = original.type;
|
|
689
|
+
result.category = original.category;
|
|
690
|
+
result.keywords = original.keywords;
|
|
691
|
+
result.subobjects = original.subobjects;
|
|
692
|
+
result.totalFaces = original.totalFaces;
|
|
693
|
+
result.startingConstructionStep = original.startingConstructionStep;
|
|
694
|
+
result.materials = original.materials;
|
|
695
|
+
result.group = null;
|
|
696
|
+
return result;
|
|
537
697
|
|
|
538
|
-
|
|
539
|
-
subobjectURL = 'models/' + subobjectURL;
|
|
540
|
-
locationState = locationState + 1;
|
|
541
|
-
break;
|
|
698
|
+
}
|
|
542
699
|
|
|
543
|
-
|
|
544
|
-
subobjectURL = fileName.substring( 0, fileName.lastIndexOf( '/' ) + 1 ) + subobjectURL;
|
|
545
|
-
locationState = locationState + 1;
|
|
546
|
-
break;
|
|
700
|
+
async fetchData( fileName ) {
|
|
547
701
|
|
|
548
|
-
|
|
702
|
+
let triedLowerCase = false;
|
|
703
|
+
let locationState = FILE_LOCATION_AS_IS;
|
|
704
|
+
while ( locationState !== FILE_LOCATION_NOT_FOUND ) {
|
|
549
705
|
|
|
550
|
-
|
|
706
|
+
let subobjectURL = fileName;
|
|
707
|
+
switch ( locationState ) {
|
|
551
708
|
|
|
552
|
-
|
|
553
|
-
|
|
709
|
+
case FILE_LOCATION_AS_IS:
|
|
710
|
+
locationState = locationState + 1;
|
|
711
|
+
break;
|
|
554
712
|
|
|
555
|
-
|
|
713
|
+
case FILE_LOCATION_TRY_PARTS:
|
|
714
|
+
subobjectURL = 'parts/' + subobjectURL;
|
|
715
|
+
locationState = locationState + 1;
|
|
716
|
+
break;
|
|
556
717
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
locationState = FILE_LOCATION_AS_IS;
|
|
718
|
+
case FILE_LOCATION_TRY_P:
|
|
719
|
+
subobjectURL = 'p/' + subobjectURL;
|
|
720
|
+
locationState = locationState + 1;
|
|
721
|
+
break;
|
|
562
722
|
|
|
563
|
-
|
|
723
|
+
case FILE_LOCATION_TRY_MODELS:
|
|
724
|
+
subobjectURL = 'models/' + subobjectURL;
|
|
725
|
+
locationState = locationState + 1;
|
|
726
|
+
break;
|
|
564
727
|
|
|
565
|
-
|
|
728
|
+
case FILE_LOCATION_TRY_RELATIVE:
|
|
729
|
+
subobjectURL = fileName.substring( 0, fileName.lastIndexOf( '/' ) + 1 ) + subobjectURL;
|
|
730
|
+
locationState = locationState + 1;
|
|
731
|
+
break;
|
|
566
732
|
|
|
567
|
-
|
|
733
|
+
case FILE_LOCATION_TRY_ABSOLUTE:
|
|
568
734
|
|
|
569
|
-
|
|
570
|
-
const fileLoader = new FileLoader( loader.manager );
|
|
571
|
-
fileLoader.setPath( loader.partsLibraryPath );
|
|
572
|
-
fileLoader.setRequestHeader( loader.requestHeader );
|
|
573
|
-
fileLoader.setWithCredentials( loader.withCredentials );
|
|
735
|
+
if ( triedLowerCase ) {
|
|
574
736
|
|
|
575
|
-
|
|
737
|
+
// Try absolute path
|
|
738
|
+
locationState = FILE_LOCATION_NOT_FOUND;
|
|
576
739
|
|
|
577
|
-
|
|
578
|
-
this.setData( fileName, text );
|
|
579
|
-
resolve( text );
|
|
580
|
-
return;
|
|
740
|
+
} else {
|
|
581
741
|
|
|
582
|
-
|
|
742
|
+
// Next attempt is lower case
|
|
743
|
+
fileName = fileName.toLowerCase();
|
|
744
|
+
subobjectURL = fileName;
|
|
745
|
+
triedLowerCase = true;
|
|
746
|
+
locationState = FILE_LOCATION_AS_IS;
|
|
583
747
|
|
|
584
|
-
|
|
748
|
+
}
|
|
585
749
|
|
|
586
|
-
|
|
750
|
+
break;
|
|
587
751
|
|
|
588
752
|
}
|
|
589
753
|
|
|
590
|
-
|
|
754
|
+
const loader = this.loader;
|
|
755
|
+
const fileLoader = new FileLoader( loader.manager );
|
|
756
|
+
fileLoader.setPath( loader.partsLibraryPath );
|
|
757
|
+
fileLoader.setRequestHeader( loader.requestHeader );
|
|
758
|
+
fileLoader.setWithCredentials( loader.withCredentials );
|
|
591
759
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
return this.cache[ fileName ];
|
|
595
|
-
|
|
596
|
-
}
|
|
760
|
+
try {
|
|
597
761
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
function sortByMaterial( a, b ) {
|
|
762
|
+
const text = await fileLoader.loadAsync( subobjectURL );
|
|
763
|
+
return text;
|
|
601
764
|
|
|
602
|
-
|
|
765
|
+
} catch {
|
|
603
766
|
|
|
604
|
-
|
|
767
|
+
continue;
|
|
605
768
|
|
|
606
|
-
|
|
769
|
+
}
|
|
607
770
|
|
|
608
|
-
|
|
771
|
+
}
|
|
609
772
|
|
|
610
|
-
|
|
773
|
+
throw new Error( 'LDrawLoader: Subobject "' + fileName + '" could not be loaded.' );
|
|
611
774
|
|
|
612
775
|
}
|
|
613
776
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
777
|
+
parse( text, fileName = null ) {
|
|
617
778
|
|
|
618
|
-
|
|
779
|
+
const loader = this.loader;
|
|
619
780
|
|
|
620
|
-
|
|
621
|
-
|
|
781
|
+
// final results
|
|
782
|
+
const faces = [];
|
|
783
|
+
const lineSegments = [];
|
|
784
|
+
const conditionalSegments = [];
|
|
785
|
+
const subobjects = [];
|
|
786
|
+
const materials = {};
|
|
622
787
|
|
|
623
|
-
|
|
624
|
-
elements.sort( sortByMaterial );
|
|
788
|
+
const getLocalMaterial = colorCode => {
|
|
625
789
|
|
|
626
|
-
|
|
790
|
+
return materials[ colorCode ] || null;
|
|
627
791
|
|
|
628
|
-
|
|
792
|
+
};
|
|
629
793
|
|
|
630
|
-
|
|
794
|
+
let type = 'Model';
|
|
795
|
+
let category = null;
|
|
796
|
+
let keywords = null;
|
|
797
|
+
let totalFaces = 0;
|
|
631
798
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
const materials = [];
|
|
799
|
+
// split into lines
|
|
800
|
+
if ( text.indexOf( '\r\n' ) !== - 1 ) {
|
|
635
801
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
let prevMaterial = null;
|
|
639
|
-
let index0 = 0;
|
|
640
|
-
let numGroupVerts = 0;
|
|
641
|
-
let offset = 0;
|
|
802
|
+
// This is faster than String.split with regex that splits on both
|
|
803
|
+
text = text.replace( /\r\n/g, '\n' );
|
|
642
804
|
|
|
643
|
-
|
|
805
|
+
}
|
|
644
806
|
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
if ( vertices.length === 4 ) {
|
|
807
|
+
const lines = text.split( '\n' );
|
|
808
|
+
const numLines = lines.length;
|
|
648
809
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
quadArray[ 3 ] = vertices[ 0 ];
|
|
653
|
-
quadArray[ 4 ] = vertices[ 2 ];
|
|
654
|
-
quadArray[ 5 ] = vertices[ 3 ];
|
|
655
|
-
vertices = quadArray;
|
|
810
|
+
let parsingEmbeddedFiles = false;
|
|
811
|
+
let currentEmbeddedFileName = null;
|
|
812
|
+
let currentEmbeddedText = null;
|
|
656
813
|
|
|
657
|
-
|
|
814
|
+
let bfcCertified = false;
|
|
815
|
+
let bfcCCW = true;
|
|
816
|
+
let bfcInverted = false;
|
|
817
|
+
let bfcCull = true;
|
|
658
818
|
|
|
659
|
-
|
|
819
|
+
let startingConstructionStep = false;
|
|
660
820
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
positions[ index + 0 ] = v.x;
|
|
664
|
-
positions[ index + 1 ] = v.y;
|
|
665
|
-
positions[ index + 2 ] = v.z;
|
|
821
|
+
// Parse all line commands
|
|
822
|
+
for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) {
|
|
666
823
|
|
|
667
|
-
|
|
824
|
+
const line = lines[ lineIndex ];
|
|
668
825
|
|
|
669
|
-
|
|
826
|
+
if ( line.length === 0 ) continue;
|
|
670
827
|
|
|
671
|
-
|
|
672
|
-
if ( elemNormals.length === 4 ) {
|
|
828
|
+
if ( parsingEmbeddedFiles ) {
|
|
673
829
|
|
|
674
|
-
|
|
675
|
-
quadArray[ 1 ] = elemNormals[ 1 ];
|
|
676
|
-
quadArray[ 2 ] = elemNormals[ 2 ];
|
|
677
|
-
quadArray[ 3 ] = elemNormals[ 0 ];
|
|
678
|
-
quadArray[ 4 ] = elemNormals[ 2 ];
|
|
679
|
-
quadArray[ 5 ] = elemNormals[ 3 ];
|
|
680
|
-
elemNormals = quadArray;
|
|
830
|
+
if ( line.startsWith( '0 FILE ' ) ) {
|
|
681
831
|
|
|
682
|
-
|
|
832
|
+
// Save previous embedded file in the cache
|
|
833
|
+
this.setData( currentEmbeddedFileName, currentEmbeddedText );
|
|
683
834
|
|
|
684
|
-
|
|
835
|
+
// New embedded text file
|
|
836
|
+
currentEmbeddedFileName = line.substring( 7 );
|
|
837
|
+
currentEmbeddedText = '';
|
|
685
838
|
|
|
686
|
-
|
|
687
|
-
if ( elemNormals[ j ] ) {
|
|
839
|
+
} else {
|
|
688
840
|
|
|
689
|
-
|
|
841
|
+
currentEmbeddedText += line + '\n';
|
|
690
842
|
|
|
691
843
|
}
|
|
692
844
|
|
|
693
|
-
|
|
694
|
-
normals[ index + 0 ] = n.x;
|
|
695
|
-
normals[ index + 1 ] = n.y;
|
|
696
|
-
normals[ index + 2 ] = n.z;
|
|
845
|
+
continue;
|
|
697
846
|
|
|
698
847
|
}
|
|
699
848
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
if ( prevMaterial !== elem.material ) {
|
|
849
|
+
const lp = new LineParser( line, lineIndex + 1 );
|
|
850
|
+
lp.seekNonSpace();
|
|
703
851
|
|
|
704
|
-
if (
|
|
852
|
+
if ( lp.isAtTheEnd() ) {
|
|
705
853
|
|
|
706
|
-
|
|
854
|
+
// Empty line
|
|
855
|
+
continue;
|
|
707
856
|
|
|
708
857
|
}
|
|
709
858
|
|
|
710
|
-
|
|
859
|
+
// Parse the line type
|
|
860
|
+
const lineType = lp.getToken();
|
|
711
861
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
862
|
+
let material;
|
|
863
|
+
let colorCode;
|
|
864
|
+
let segment;
|
|
865
|
+
let ccw;
|
|
866
|
+
let doubleSided;
|
|
867
|
+
let v0, v1, v2, v3, c0, c1;
|
|
715
868
|
|
|
716
|
-
|
|
869
|
+
switch ( lineType ) {
|
|
717
870
|
|
|
718
|
-
|
|
871
|
+
// Line type 0: Comment or META
|
|
872
|
+
case '0':
|
|
719
873
|
|
|
720
|
-
|
|
874
|
+
// Parse meta directive
|
|
875
|
+
const meta = lp.getToken();
|
|
721
876
|
|
|
722
|
-
|
|
877
|
+
if ( meta ) {
|
|
723
878
|
|
|
724
|
-
|
|
879
|
+
switch ( meta ) {
|
|
725
880
|
|
|
726
|
-
|
|
881
|
+
case '!LDRAW_ORG':
|
|
727
882
|
|
|
728
|
-
|
|
883
|
+
type = lp.getToken();
|
|
884
|
+
break;
|
|
729
885
|
|
|
730
|
-
|
|
886
|
+
case '!COLOUR':
|
|
731
887
|
|
|
732
|
-
|
|
888
|
+
material = loader.parseColorMetaDirective( lp );
|
|
889
|
+
if ( material ) {
|
|
733
890
|
|
|
734
|
-
|
|
891
|
+
materials[ material.userData.code ] = material;
|
|
735
892
|
|
|
736
|
-
|
|
893
|
+
} else {
|
|
737
894
|
|
|
738
|
-
|
|
895
|
+
console.warn( 'LDrawLoader: Error parsing material' + lp.getLineNumberString() );
|
|
739
896
|
|
|
740
|
-
|
|
897
|
+
}
|
|
741
898
|
|
|
742
|
-
|
|
899
|
+
break;
|
|
743
900
|
|
|
744
|
-
|
|
901
|
+
case '!CATEGORY':
|
|
745
902
|
|
|
746
|
-
|
|
903
|
+
category = lp.getToken();
|
|
904
|
+
break;
|
|
747
905
|
|
|
748
|
-
|
|
906
|
+
case '!KEYWORDS':
|
|
749
907
|
|
|
750
|
-
|
|
908
|
+
const newKeywords = lp.getRemainingString().split( ',' );
|
|
909
|
+
if ( newKeywords.length > 0 ) {
|
|
751
910
|
|
|
752
|
-
|
|
911
|
+
if ( ! keywords ) {
|
|
753
912
|
|
|
754
|
-
|
|
913
|
+
keywords = [];
|
|
755
914
|
|
|
756
|
-
|
|
757
|
-
const controlArray1 = new Float32Array( elements.length * 3 * 2 );
|
|
758
|
-
const directionArray = new Float32Array( elements.length * 3 * 2 );
|
|
759
|
-
for ( let i = 0, l = elements.length; i < l; i ++ ) {
|
|
915
|
+
}
|
|
760
916
|
|
|
761
|
-
|
|
762
|
-
const vertices = os.vertices;
|
|
763
|
-
const controlPoints = os.controlPoints;
|
|
764
|
-
const c0 = controlPoints[ 0 ];
|
|
765
|
-
const c1 = controlPoints[ 1 ];
|
|
766
|
-
const v0 = vertices[ 0 ];
|
|
767
|
-
const v1 = vertices[ 1 ];
|
|
768
|
-
const index = i * 3 * 2;
|
|
769
|
-
controlArray0[ index + 0 ] = c0.x;
|
|
770
|
-
controlArray0[ index + 1 ] = c0.y;
|
|
771
|
-
controlArray0[ index + 2 ] = c0.z;
|
|
772
|
-
controlArray0[ index + 3 ] = c0.x;
|
|
773
|
-
controlArray0[ index + 4 ] = c0.y;
|
|
774
|
-
controlArray0[ index + 5 ] = c0.z;
|
|
917
|
+
newKeywords.forEach( function ( keyword ) {
|
|
775
918
|
|
|
776
|
-
|
|
777
|
-
controlArray1[ index + 1 ] = c1.y;
|
|
778
|
-
controlArray1[ index + 2 ] = c1.z;
|
|
779
|
-
controlArray1[ index + 3 ] = c1.x;
|
|
780
|
-
controlArray1[ index + 4 ] = c1.y;
|
|
781
|
-
controlArray1[ index + 5 ] = c1.z;
|
|
919
|
+
keywords.push( keyword.trim() );
|
|
782
920
|
|
|
783
|
-
|
|
784
|
-
directionArray[ index + 1 ] = v1.y - v0.y;
|
|
785
|
-
directionArray[ index + 2 ] = v1.z - v0.z;
|
|
786
|
-
directionArray[ index + 3 ] = v1.x - v0.x;
|
|
787
|
-
directionArray[ index + 4 ] = v1.y - v0.y;
|
|
788
|
-
directionArray[ index + 5 ] = v1.z - v0.z;
|
|
921
|
+
} );
|
|
789
922
|
|
|
790
|
-
|
|
923
|
+
}
|
|
791
924
|
|
|
792
|
-
|
|
793
|
-
bufferGeometry.setAttribute( 'control1', new BufferAttribute( controlArray1, 3, false ) );
|
|
794
|
-
bufferGeometry.setAttribute( 'direction', new BufferAttribute( directionArray, 3, false ) );
|
|
925
|
+
break;
|
|
795
926
|
|
|
796
|
-
|
|
927
|
+
case 'FILE':
|
|
797
928
|
|
|
798
|
-
|
|
929
|
+
if ( lineIndex > 0 ) {
|
|
799
930
|
|
|
800
|
-
|
|
931
|
+
// Start embedded text files parsing
|
|
932
|
+
parsingEmbeddedFiles = true;
|
|
933
|
+
currentEmbeddedFileName = lp.getRemainingString();
|
|
934
|
+
currentEmbeddedText = '';
|
|
801
935
|
|
|
802
|
-
|
|
936
|
+
bfcCertified = false;
|
|
937
|
+
bfcCCW = true;
|
|
803
938
|
|
|
804
|
-
|
|
939
|
+
}
|
|
805
940
|
|
|
806
|
-
|
|
941
|
+
break;
|
|
807
942
|
|
|
808
|
-
|
|
943
|
+
case 'BFC':
|
|
809
944
|
|
|
810
|
-
|
|
811
|
-
|
|
945
|
+
// Changes to the backface culling state
|
|
946
|
+
while ( ! lp.isAtTheEnd() ) {
|
|
812
947
|
|
|
813
|
-
|
|
814
|
-
// This also allows to handle the embedded text files ("0 FILE" lines)
|
|
815
|
-
this.cache = new LDrawFileCache( this );
|
|
948
|
+
const token = lp.getToken();
|
|
816
949
|
|
|
817
|
-
|
|
818
|
-
this.fileMap = null;
|
|
950
|
+
switch ( token ) {
|
|
819
951
|
|
|
820
|
-
|
|
952
|
+
case 'CERTIFY':
|
|
953
|
+
case 'NOCERTIFY':
|
|
821
954
|
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
this.parseColourMetaDirective( new LineParser( 'Main_Colour CODE 16 VALUE #FF8080 EDGE #333333' ) ),
|
|
825
|
-
this.parseColourMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) )
|
|
826
|
-
] );
|
|
955
|
+
bfcCertified = token === 'CERTIFY';
|
|
956
|
+
bfcCCW = true;
|
|
827
957
|
|
|
828
|
-
|
|
829
|
-
// If not (the default), only one object which contains all the merged primitives will be created.
|
|
830
|
-
this.separateObjects = false;
|
|
958
|
+
break;
|
|
831
959
|
|
|
832
|
-
|
|
833
|
-
|
|
960
|
+
case 'CW':
|
|
961
|
+
case 'CCW':
|
|
834
962
|
|
|
835
|
-
|
|
836
|
-
this.partsLibraryPath = '';
|
|
963
|
+
bfcCCW = token === 'CCW';
|
|
837
964
|
|
|
838
|
-
|
|
965
|
+
break;
|
|
839
966
|
|
|
840
|
-
|
|
967
|
+
case 'INVERTNEXT':
|
|
841
968
|
|
|
842
|
-
|
|
843
|
-
return this;
|
|
969
|
+
bfcInverted = true;
|
|
844
970
|
|
|
845
|
-
|
|
971
|
+
break;
|
|
846
972
|
|
|
847
|
-
|
|
973
|
+
case 'CLIP':
|
|
974
|
+
case 'NOCLIP':
|
|
848
975
|
|
|
849
|
-
|
|
850
|
-
fileLoader.setPath( this.path );
|
|
851
|
-
fileLoader.setRequestHeader( this.requestHeader );
|
|
852
|
-
fileLoader.setWithCredentials( this.withCredentials );
|
|
976
|
+
bfcCull = token === 'CLIP';
|
|
853
977
|
|
|
854
|
-
|
|
855
|
-
const colorLineRegex = /^0 !COLOUR/;
|
|
856
|
-
const lines = text.split( /[\n\r]/g );
|
|
857
|
-
const materials = [];
|
|
858
|
-
for ( let i = 0, l = lines.length; i < l; i ++ ) {
|
|
978
|
+
break;
|
|
859
979
|
|
|
860
|
-
|
|
861
|
-
if ( colorLineRegex.test( line ) ) {
|
|
980
|
+
default:
|
|
862
981
|
|
|
863
|
-
|
|
864
|
-
const material = this.parseColourMetaDirective( new LineParser( directive ) );
|
|
865
|
-
materials.push( material );
|
|
982
|
+
console.warn( 'THREE.LDrawLoader: BFC directive "' + token + '" is unknown.' );
|
|
866
983
|
|
|
867
|
-
|
|
984
|
+
break;
|
|
868
985
|
|
|
869
|
-
|
|
986
|
+
}
|
|
870
987
|
|
|
871
|
-
|
|
988
|
+
}
|
|
872
989
|
|
|
873
|
-
|
|
990
|
+
break;
|
|
874
991
|
|
|
875
|
-
|
|
992
|
+
case 'STEP':
|
|
876
993
|
|
|
877
|
-
|
|
994
|
+
startingConstructionStep = true;
|
|
878
995
|
|
|
879
|
-
|
|
996
|
+
break;
|
|
880
997
|
|
|
881
|
-
|
|
998
|
+
default:
|
|
999
|
+
// Other meta directives are not implemented
|
|
1000
|
+
break;
|
|
882
1001
|
|
|
883
|
-
|
|
884
|
-
fileLoader.setPath( this.path );
|
|
885
|
-
fileLoader.setRequestHeader( this.requestHeader );
|
|
886
|
-
fileLoader.setWithCredentials( this.withCredentials );
|
|
887
|
-
fileLoader.load( url, text => {
|
|
1002
|
+
}
|
|
888
1003
|
|
|
889
|
-
|
|
890
|
-
.then( function ( result ) {
|
|
1004
|
+
}
|
|
891
1005
|
|
|
892
|
-
|
|
1006
|
+
break;
|
|
893
1007
|
|
|
894
|
-
|
|
1008
|
+
// Line type 1: Sub-object file
|
|
1009
|
+
case '1':
|
|
895
1010
|
|
|
896
|
-
|
|
1011
|
+
colorCode = lp.getToken();
|
|
1012
|
+
material = getLocalMaterial( colorCode );
|
|
897
1013
|
|
|
898
|
-
|
|
1014
|
+
const posX = parseFloat( lp.getToken() );
|
|
1015
|
+
const posY = parseFloat( lp.getToken() );
|
|
1016
|
+
const posZ = parseFloat( lp.getToken() );
|
|
1017
|
+
const m0 = parseFloat( lp.getToken() );
|
|
1018
|
+
const m1 = parseFloat( lp.getToken() );
|
|
1019
|
+
const m2 = parseFloat( lp.getToken() );
|
|
1020
|
+
const m3 = parseFloat( lp.getToken() );
|
|
1021
|
+
const m4 = parseFloat( lp.getToken() );
|
|
1022
|
+
const m5 = parseFloat( lp.getToken() );
|
|
1023
|
+
const m6 = parseFloat( lp.getToken() );
|
|
1024
|
+
const m7 = parseFloat( lp.getToken() );
|
|
1025
|
+
const m8 = parseFloat( lp.getToken() );
|
|
899
1026
|
|
|
900
|
-
|
|
1027
|
+
const matrix = new Matrix4().set(
|
|
1028
|
+
m0, m1, m2, posX,
|
|
1029
|
+
m3, m4, m5, posY,
|
|
1030
|
+
m6, m7, m8, posZ,
|
|
1031
|
+
0, 0, 0, 1
|
|
1032
|
+
);
|
|
901
1033
|
|
|
902
|
-
|
|
903
|
-
this.processObject( text, null, path, this.rootParseScope )
|
|
904
|
-
.then( function ( result ) {
|
|
1034
|
+
let fileName = lp.getRemainingString().trim().replace( /\\/g, '/' );
|
|
905
1035
|
|
|
906
|
-
|
|
1036
|
+
if ( loader.fileMap[ fileName ] ) {
|
|
907
1037
|
|
|
908
|
-
|
|
1038
|
+
// Found the subobject path in the preloaded file path map
|
|
1039
|
+
fileName = loader.fileMap[ fileName ];
|
|
909
1040
|
|
|
910
|
-
|
|
1041
|
+
} else {
|
|
911
1042
|
|
|
912
|
-
|
|
1043
|
+
// Standardized subfolders
|
|
1044
|
+
if ( fileName.startsWith( 's/' ) ) {
|
|
913
1045
|
|
|
914
|
-
|
|
915
|
-
this.rootParseScope = this.newParseScopeLevel( materials );
|
|
916
|
-
this.rootParseScope.isFromParse = false;
|
|
1046
|
+
fileName = 'parts/' + fileName;
|
|
917
1047
|
|
|
918
|
-
|
|
1048
|
+
} else if ( fileName.startsWith( '48/' ) ) {
|
|
919
1049
|
|
|
920
|
-
|
|
1050
|
+
fileName = 'p/' + fileName;
|
|
921
1051
|
|
|
922
|
-
|
|
1052
|
+
}
|
|
923
1053
|
|
|
924
|
-
|
|
1054
|
+
}
|
|
925
1055
|
|
|
926
|
-
|
|
1056
|
+
subobjects.push( {
|
|
1057
|
+
material: material,
|
|
1058
|
+
colorCode: colorCode,
|
|
1059
|
+
matrix: matrix,
|
|
1060
|
+
fileName: fileName,
|
|
1061
|
+
inverted: bfcInverted,
|
|
1062
|
+
startingConstructionStep: startingConstructionStep
|
|
1063
|
+
} );
|
|
927
1064
|
|
|
928
|
-
|
|
1065
|
+
bfcInverted = false;
|
|
929
1066
|
|
|
930
|
-
|
|
1067
|
+
break;
|
|
1068
|
+
|
|
1069
|
+
// Line type 2: Line segment
|
|
1070
|
+
case '2':
|
|
1071
|
+
|
|
1072
|
+
colorCode = lp.getToken();
|
|
1073
|
+
material = getLocalMaterial( colorCode );
|
|
1074
|
+
v0 = lp.getVector();
|
|
1075
|
+
v1 = lp.getVector();
|
|
1076
|
+
|
|
1077
|
+
segment = {
|
|
1078
|
+
material: material,
|
|
1079
|
+
colorCode: colorCode,
|
|
1080
|
+
vertices: [ v0, v1 ],
|
|
1081
|
+
};
|
|
1082
|
+
|
|
1083
|
+
lineSegments.push( segment );
|
|
1084
|
+
|
|
1085
|
+
break;
|
|
1086
|
+
|
|
1087
|
+
// Line type 5: Conditional Line segment
|
|
1088
|
+
case '5':
|
|
1089
|
+
|
|
1090
|
+
colorCode = lp.getToken();
|
|
1091
|
+
material = getLocalMaterial( colorCode );
|
|
1092
|
+
v0 = lp.getVector();
|
|
1093
|
+
v1 = lp.getVector();
|
|
1094
|
+
c0 = lp.getVector();
|
|
1095
|
+
c1 = lp.getVector();
|
|
1096
|
+
|
|
1097
|
+
segment = {
|
|
1098
|
+
material: material,
|
|
1099
|
+
colorCode: colorCode,
|
|
1100
|
+
vertices: [ v0, v1 ],
|
|
1101
|
+
controlPoints: [ c0, c1 ],
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
conditionalSegments.push( segment );
|
|
1105
|
+
|
|
1106
|
+
break;
|
|
1107
|
+
|
|
1108
|
+
// Line type 3: Triangle
|
|
1109
|
+
case '3':
|
|
1110
|
+
|
|
1111
|
+
colorCode = lp.getToken();
|
|
1112
|
+
material = getLocalMaterial( colorCode );
|
|
1113
|
+
ccw = bfcCCW;
|
|
1114
|
+
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1115
|
+
|
|
1116
|
+
if ( ccw === true ) {
|
|
1117
|
+
|
|
1118
|
+
v0 = lp.getVector();
|
|
1119
|
+
v1 = lp.getVector();
|
|
1120
|
+
v2 = lp.getVector();
|
|
1121
|
+
|
|
1122
|
+
} else {
|
|
1123
|
+
|
|
1124
|
+
v2 = lp.getVector();
|
|
1125
|
+
v1 = lp.getVector();
|
|
1126
|
+
v0 = lp.getVector();
|
|
1127
|
+
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
faces.push( {
|
|
1131
|
+
material: material,
|
|
1132
|
+
colorCode: colorCode,
|
|
1133
|
+
faceNormal: null,
|
|
1134
|
+
vertices: [ v0, v1, v2 ],
|
|
1135
|
+
normals: [ null, null, null ],
|
|
1136
|
+
} );
|
|
1137
|
+
totalFaces ++;
|
|
1138
|
+
|
|
1139
|
+
if ( doubleSided === true ) {
|
|
1140
|
+
|
|
1141
|
+
faces.push( {
|
|
1142
|
+
material: material,
|
|
1143
|
+
colorCode: colorCode,
|
|
1144
|
+
faceNormal: null,
|
|
1145
|
+
vertices: [ v2, v1, v0 ],
|
|
1146
|
+
normals: [ null, null, null ],
|
|
1147
|
+
} );
|
|
1148
|
+
totalFaces ++;
|
|
1149
|
+
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
break;
|
|
1153
|
+
|
|
1154
|
+
// Line type 4: Quadrilateral
|
|
1155
|
+
case '4':
|
|
931
1156
|
|
|
932
|
-
|
|
1157
|
+
colorCode = lp.getToken();
|
|
1158
|
+
material = getLocalMaterial( colorCode );
|
|
1159
|
+
ccw = bfcCCW;
|
|
1160
|
+
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1161
|
+
|
|
1162
|
+
if ( ccw === true ) {
|
|
1163
|
+
|
|
1164
|
+
v0 = lp.getVector();
|
|
1165
|
+
v1 = lp.getVector();
|
|
1166
|
+
v2 = lp.getVector();
|
|
1167
|
+
v3 = lp.getVector();
|
|
1168
|
+
|
|
1169
|
+
} else {
|
|
933
1170
|
|
|
934
|
-
|
|
1171
|
+
v3 = lp.getVector();
|
|
1172
|
+
v2 = lp.getVector();
|
|
1173
|
+
v1 = lp.getVector();
|
|
1174
|
+
v0 = lp.getVector();
|
|
935
1175
|
|
|
936
|
-
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
// specifically place the triangle diagonal in the v0 and v1 slots so we can
|
|
1179
|
+
// account for the doubling of vertices later when smoothing normals.
|
|
1180
|
+
faces.push( {
|
|
1181
|
+
material: material,
|
|
1182
|
+
colorCode: colorCode,
|
|
1183
|
+
faceNormal: null,
|
|
1184
|
+
vertices: [ v0, v1, v2, v3 ],
|
|
1185
|
+
normals: [ null, null, null, null ],
|
|
1186
|
+
} );
|
|
1187
|
+
totalFaces += 2;
|
|
1188
|
+
|
|
1189
|
+
if ( doubleSided === true ) {
|
|
1190
|
+
|
|
1191
|
+
faces.push( {
|
|
1192
|
+
material: material,
|
|
1193
|
+
colorCode: colorCode,
|
|
1194
|
+
faceNormal: null,
|
|
1195
|
+
vertices: [ v3, v2, v1, v0 ],
|
|
1196
|
+
normals: [ null, null, null, null ],
|
|
1197
|
+
} );
|
|
1198
|
+
totalFaces += 2;
|
|
937
1199
|
|
|
938
|
-
|
|
1200
|
+
}
|
|
939
1201
|
|
|
940
|
-
|
|
1202
|
+
break;
|
|
941
1203
|
|
|
942
|
-
|
|
943
|
-
|
|
1204
|
+
default:
|
|
1205
|
+
throw new Error( 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.' );
|
|
944
1206
|
|
|
945
1207
|
}
|
|
946
1208
|
|
|
947
1209
|
}
|
|
948
1210
|
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
category
|
|
961
|
-
keywords
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
matrix: new Matrix4(),
|
|
969
|
-
type: 'Model',
|
|
970
|
-
groupObject: null,
|
|
971
|
-
|
|
972
|
-
// If false, it is a root material scope previous to parse
|
|
973
|
-
isFromParse: true,
|
|
974
|
-
|
|
975
|
-
faces: [],
|
|
976
|
-
lineSegments: [],
|
|
977
|
-
conditionalSegments: [],
|
|
978
|
-
totalFaces: 0,
|
|
979
|
-
|
|
980
|
-
// If true, this object is the start of a construction step
|
|
981
|
-
startingConstructionStep: false
|
|
1211
|
+
if ( parsingEmbeddedFiles ) {
|
|
1212
|
+
|
|
1213
|
+
this.setData( currentEmbeddedFileName, currentEmbeddedText );
|
|
1214
|
+
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
return {
|
|
1218
|
+
faces,
|
|
1219
|
+
conditionalSegments,
|
|
1220
|
+
lineSegments,
|
|
1221
|
+
type,
|
|
1222
|
+
category,
|
|
1223
|
+
keywords,
|
|
1224
|
+
subobjects,
|
|
1225
|
+
totalFaces,
|
|
1226
|
+
startingConstructionStep,
|
|
1227
|
+
materials,
|
|
1228
|
+
fileName,
|
|
1229
|
+
group: null
|
|
982
1230
|
};
|
|
983
1231
|
|
|
984
|
-
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
// returns an (optionally cloned) instance of the data
|
|
1235
|
+
getData( fileName, clone = true ) {
|
|
1236
|
+
|
|
1237
|
+
const key = fileName.toLowerCase();
|
|
1238
|
+
const result = this._cache[ key ];
|
|
1239
|
+
if ( result === null || result instanceof Promise ) {
|
|
1240
|
+
|
|
1241
|
+
return null;
|
|
1242
|
+
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
if ( clone ) {
|
|
1246
|
+
|
|
1247
|
+
return this.cloneResult( result );
|
|
1248
|
+
|
|
1249
|
+
} else {
|
|
1250
|
+
|
|
1251
|
+
return result;
|
|
1252
|
+
|
|
1253
|
+
}
|
|
985
1254
|
|
|
986
1255
|
}
|
|
987
1256
|
|
|
988
|
-
|
|
1257
|
+
// kicks off a fetch and parse of the requested data if it hasn't already been loaded. Returns when
|
|
1258
|
+
// the data is ready to use and can be retrieved synchronously with "getData".
|
|
1259
|
+
async ensureDataLoaded( fileName ) {
|
|
989
1260
|
|
|
990
|
-
|
|
1261
|
+
const key = fileName.toLowerCase();
|
|
1262
|
+
if ( ! ( key in this._cache ) ) {
|
|
991
1263
|
|
|
992
|
-
|
|
1264
|
+
// replace the promise with a copy of the parsed data for immediate processing
|
|
1265
|
+
this._cache[ key ] = this.fetchData( fileName ).then( text => {
|
|
993
1266
|
|
|
994
|
-
|
|
1267
|
+
const info = this.parse( text, fileName );
|
|
1268
|
+
this._cache[ key ] = info;
|
|
1269
|
+
return info;
|
|
995
1270
|
|
|
996
|
-
|
|
1271
|
+
} );
|
|
997
1272
|
|
|
998
1273
|
}
|
|
999
1274
|
|
|
1000
|
-
|
|
1275
|
+
await this._cache[ key ];
|
|
1001
1276
|
|
|
1002
|
-
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
// sets the data in the cache from parsed data
|
|
1280
|
+
setData( fileName, text ) {
|
|
1281
|
+
|
|
1282
|
+
const key = fileName.toLowerCase();
|
|
1283
|
+
this._cache[ key ] = this.parse( text, fileName );
|
|
1003
1284
|
|
|
1004
1285
|
}
|
|
1005
1286
|
|
|
1006
|
-
|
|
1287
|
+
}
|
|
1007
1288
|
|
|
1008
|
-
|
|
1289
|
+
// returns the material for an associated color code. If the color code is 16 for a face or 24 for
|
|
1290
|
+
// an edge then the passthroughColorCode is used.
|
|
1291
|
+
function getMaterialFromCode( colorCode, parentColorCode, materialHierarchy, forEdge ) {
|
|
1009
1292
|
|
|
1010
|
-
|
|
1293
|
+
const isPassthrough = ! forEdge && colorCode === MAIN_COLOUR_CODE || forEdge && colorCode === MAIN_EDGE_COLOUR_CODE;
|
|
1294
|
+
if ( isPassthrough ) {
|
|
1011
1295
|
|
|
1012
|
-
|
|
1296
|
+
colorCode = parentColorCode;
|
|
1013
1297
|
|
|
1014
|
-
|
|
1298
|
+
}
|
|
1015
1299
|
|
|
1016
|
-
|
|
1300
|
+
return materialHierarchy[ colorCode ] || null;
|
|
1017
1301
|
|
|
1018
|
-
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
// Class used to parse and build LDraw parts as three.js objects and cache them if they're a "Part" type.
|
|
1305
|
+
class LDrawPartsGeometryCache {
|
|
1306
|
+
|
|
1307
|
+
constructor( loader ) {
|
|
1308
|
+
|
|
1309
|
+
this.loader = loader;
|
|
1310
|
+
this.parseCache = new LDrawParsedCache( loader );
|
|
1311
|
+
this._cache = {};
|
|
1312
|
+
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
// Convert the given file information into a mesh by processing subobjects.
|
|
1316
|
+
async processIntoMesh( info ) {
|
|
1317
|
+
|
|
1318
|
+
const loader = this.loader;
|
|
1319
|
+
const parseCache = this.parseCache;
|
|
1320
|
+
const faceMaterials = new Set();
|
|
1321
|
+
|
|
1322
|
+
// Processes the part subobject information to load child parts and merge geometry onto part
|
|
1323
|
+
// piece object.
|
|
1324
|
+
const processInfoSubobjects = async ( info, subobject = null ) => {
|
|
1325
|
+
|
|
1326
|
+
const subobjects = info.subobjects;
|
|
1327
|
+
const promises = [];
|
|
1328
|
+
|
|
1329
|
+
// Trigger load of all subobjects. If a subobject isn't a primitive then load it as a separate
|
|
1330
|
+
// group which lets instruction steps apply correctly.
|
|
1331
|
+
for ( let i = 0, l = subobjects.length; i < l; i ++ ) {
|
|
1332
|
+
|
|
1333
|
+
const subobject = subobjects[ i ];
|
|
1334
|
+
const promise = parseCache.ensureDataLoaded( subobject.fileName ).then( () => {
|
|
1335
|
+
|
|
1336
|
+
const subobjectInfo = parseCache.getData( subobject.fileName, false );
|
|
1337
|
+
if ( ! isPrimitiveType( subobjectInfo.type ) ) {
|
|
1338
|
+
|
|
1339
|
+
return this.loadModel( subobject.fileName ).catch( error => {
|
|
1340
|
+
|
|
1341
|
+
console.warn( error );
|
|
1342
|
+
return null;
|
|
1343
|
+
|
|
1344
|
+
} );
|
|
1345
|
+
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
return processInfoSubobjects( parseCache.getData( subobject.fileName ), subobject );
|
|
1349
|
+
|
|
1350
|
+
} );
|
|
1351
|
+
|
|
1352
|
+
promises.push( promise );
|
|
1019
1353
|
|
|
1020
|
-
|
|
1354
|
+
}
|
|
1021
1355
|
|
|
1022
|
-
const
|
|
1356
|
+
const group = new Group();
|
|
1357
|
+
group.userData.category = info.category;
|
|
1358
|
+
group.userData.keywords = info.keywords;
|
|
1359
|
+
info.group = group;
|
|
1023
1360
|
|
|
1024
|
-
|
|
1361
|
+
const subobjectInfos = await Promise.all( promises );
|
|
1362
|
+
for ( let i = 0, l = subobjectInfos.length; i < l; i ++ ) {
|
|
1025
1363
|
|
|
1026
|
-
|
|
1364
|
+
const subobject = info.subobjects[ i ];
|
|
1365
|
+
const subobjectInfo = subobjectInfos[ i ];
|
|
1027
1366
|
|
|
1028
|
-
|
|
1367
|
+
if ( subobjectInfo === null ) {
|
|
1029
1368
|
|
|
1030
|
-
|
|
1369
|
+
// the subobject failed to load
|
|
1370
|
+
continue;
|
|
1031
1371
|
|
|
1032
|
-
|
|
1372
|
+
}
|
|
1033
1373
|
|
|
1034
|
-
|
|
1374
|
+
// if the subobject was loaded as a separate group then apply the parent scopes materials
|
|
1375
|
+
if ( subobjectInfo.isGroup ) {
|
|
1035
1376
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1377
|
+
const subobjectGroup = subobjectInfo;
|
|
1378
|
+
subobject.matrix.decompose( subobjectGroup.position, subobjectGroup.quaternion, subobjectGroup.scale );
|
|
1379
|
+
subobjectGroup.userData.startingConstructionStep = subobject.startingConstructionStep;
|
|
1380
|
+
subobjectGroup.name = subobject.fileName;
|
|
1038
1381
|
|
|
1039
|
-
|
|
1382
|
+
loader.applyMaterialsToMesh( subobjectGroup, subobject.colorCode, info.materials );
|
|
1040
1383
|
|
|
1041
|
-
|
|
1384
|
+
group.add( subobjectGroup );
|
|
1385
|
+
continue;
|
|
1042
1386
|
|
|
1043
|
-
|
|
1387
|
+
}
|
|
1044
1388
|
|
|
1045
|
-
|
|
1389
|
+
// add the subobject group if it has children in case it has both children and primitives
|
|
1390
|
+
if ( subobjectInfo.group.children.length ) {
|
|
1046
1391
|
|
|
1047
|
-
|
|
1048
|
-
let colour = 0xFF00FF;
|
|
1049
|
-
let edgeColour = 0xFF00FF;
|
|
1392
|
+
group.add( subobjectInfo.group );
|
|
1050
1393
|
|
|
1051
|
-
|
|
1052
|
-
let alpha = 1;
|
|
1053
|
-
let isTransparent = false;
|
|
1054
|
-
// Self-illumination:
|
|
1055
|
-
let luminance = 0;
|
|
1394
|
+
}
|
|
1056
1395
|
|
|
1057
|
-
|
|
1396
|
+
// transform the primitives into the local space of the parent piece and append them to
|
|
1397
|
+
// to the parent primitives list.
|
|
1398
|
+
const parentLineSegments = info.lineSegments;
|
|
1399
|
+
const parentConditionalSegments = info.conditionalSegments;
|
|
1400
|
+
const parentFaces = info.faces;
|
|
1058
1401
|
|
|
1059
|
-
|
|
1402
|
+
const lineSegments = subobjectInfo.lineSegments;
|
|
1403
|
+
const conditionalSegments = subobjectInfo.conditionalSegments;
|
|
1060
1404
|
|
|
1061
|
-
|
|
1062
|
-
|
|
1405
|
+
const faces = subobjectInfo.faces;
|
|
1406
|
+
const matrix = subobject.matrix;
|
|
1407
|
+
const inverted = subobject.inverted;
|
|
1408
|
+
const matrixScaleInverted = matrix.determinant() < 0;
|
|
1409
|
+
const colorCode = subobject.colorCode;
|
|
1063
1410
|
|
|
1064
|
-
|
|
1411
|
+
const lineColorCode = colorCode === MAIN_COLOUR_CODE ? MAIN_EDGE_COLOUR_CODE : colorCode;
|
|
1412
|
+
for ( let i = 0, l = lineSegments.length; i < l; i ++ ) {
|
|
1065
1413
|
|
|
1066
|
-
|
|
1414
|
+
const ls = lineSegments[ i ];
|
|
1415
|
+
const vertices = ls.vertices;
|
|
1416
|
+
vertices[ 0 ].applyMatrix4( matrix );
|
|
1417
|
+
vertices[ 1 ].applyMatrix4( matrix );
|
|
1418
|
+
ls.colorCode = ls.colorCode === MAIN_EDGE_COLOUR_CODE ? lineColorCode : ls.colorCode;
|
|
1419
|
+
ls.material = ls.material || getMaterialFromCode( ls.colorCode, ls.colorCode, info.materials, true );
|
|
1067
1420
|
|
|
1068
|
-
|
|
1069
|
-
let token = null;
|
|
1070
|
-
while ( true ) {
|
|
1421
|
+
parentLineSegments.push( ls );
|
|
1071
1422
|
|
|
1072
|
-
|
|
1423
|
+
}
|
|
1073
1424
|
|
|
1074
|
-
|
|
1425
|
+
for ( let i = 0, l = conditionalSegments.length; i < l; i ++ ) {
|
|
1075
1426
|
|
|
1076
|
-
|
|
1427
|
+
const os = conditionalSegments[ i ];
|
|
1428
|
+
const vertices = os.vertices;
|
|
1429
|
+
const controlPoints = os.controlPoints;
|
|
1430
|
+
vertices[ 0 ].applyMatrix4( matrix );
|
|
1431
|
+
vertices[ 1 ].applyMatrix4( matrix );
|
|
1432
|
+
controlPoints[ 0 ].applyMatrix4( matrix );
|
|
1433
|
+
controlPoints[ 1 ].applyMatrix4( matrix );
|
|
1434
|
+
os.colorCode = os.colorCode === MAIN_EDGE_COLOUR_CODE ? lineColorCode : os.colorCode;
|
|
1435
|
+
os.material = os.material || getMaterialFromCode( os.colorCode, os.colorCode, info.materials, true );
|
|
1077
1436
|
|
|
1078
|
-
|
|
1437
|
+
parentConditionalSegments.push( os );
|
|
1079
1438
|
|
|
1080
|
-
|
|
1439
|
+
}
|
|
1081
1440
|
|
|
1082
|
-
|
|
1441
|
+
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
1083
1442
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1443
|
+
const tri = faces[ i ];
|
|
1444
|
+
const vertices = tri.vertices;
|
|
1445
|
+
for ( let i = 0, l = vertices.length; i < l; i ++ ) {
|
|
1086
1446
|
|
|
1087
|
-
|
|
1447
|
+
vertices[ i ].applyMatrix4( matrix );
|
|
1088
1448
|
|
|
1089
|
-
|
|
1090
|
-
if ( colour.startsWith( '0x' ) ) {
|
|
1449
|
+
}
|
|
1091
1450
|
|
|
1092
|
-
|
|
1451
|
+
tri.colorCode = tri.colorCode === MAIN_COLOUR_CODE ? colorCode : tri.colorCode;
|
|
1452
|
+
tri.material = tri.material || getMaterialFromCode( tri.colorCode, colorCode, info.materials, false );
|
|
1453
|
+
faceMaterials.add( tri.colorCode );
|
|
1093
1454
|
|
|
1094
|
-
|
|
1455
|
+
// If the scale of the object is negated then the triangle winding order
|
|
1456
|
+
// needs to be flipped.
|
|
1457
|
+
if ( matrixScaleInverted !== inverted ) {
|
|
1095
1458
|
|
|
1096
|
-
|
|
1459
|
+
vertices.reverse();
|
|
1097
1460
|
|
|
1098
1461
|
}
|
|
1099
1462
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
case 'EDGE':
|
|
1463
|
+
parentFaces.push( tri );
|
|
1103
1464
|
|
|
1104
|
-
|
|
1105
|
-
if ( edgeColour.startsWith( '0x' ) ) {
|
|
1465
|
+
}
|
|
1106
1466
|
|
|
1107
|
-
|
|
1467
|
+
info.totalFaces += subobjectInfo.totalFaces;
|
|
1108
1468
|
|
|
1109
|
-
|
|
1469
|
+
}
|
|
1110
1470
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1471
|
+
// Apply the parent subobjects pass through material code to this object. This is done several times due
|
|
1472
|
+
// to material scoping.
|
|
1473
|
+
if ( subobject ) {
|
|
1114
1474
|
|
|
1115
|
-
|
|
1475
|
+
loader.applyMaterialsToMesh( group, subobject.colorCode, info.materials );
|
|
1116
1476
|
|
|
1117
|
-
|
|
1477
|
+
}
|
|
1118
1478
|
|
|
1119
|
-
|
|
1120
|
-
edgeMaterial = edgeMaterial.userData.edgeMaterial;
|
|
1479
|
+
return info;
|
|
1121
1480
|
|
|
1122
|
-
|
|
1481
|
+
};
|
|
1123
1482
|
|
|
1124
|
-
|
|
1483
|
+
// Track material use to see if we need to use the normal smooth slow path for hard edges.
|
|
1484
|
+
for ( let i = 0, l = info.faces; i < l; i ++ ) {
|
|
1125
1485
|
|
|
1126
|
-
|
|
1486
|
+
faceMaterials.add( info.faces[ i ].colorCode );
|
|
1127
1487
|
|
|
1128
|
-
|
|
1488
|
+
}
|
|
1129
1489
|
|
|
1130
|
-
|
|
1490
|
+
await processInfoSubobjects( info );
|
|
1131
1491
|
|
|
1132
|
-
|
|
1492
|
+
if ( loader.smoothNormals ) {
|
|
1133
1493
|
|
|
1134
|
-
|
|
1494
|
+
const checkSubSegments = faceMaterials.size > 1;
|
|
1495
|
+
generateFaceNormals( info.faces );
|
|
1496
|
+
smoothNormals( info.faces, info.lineSegments, checkSubSegments );
|
|
1135
1497
|
|
|
1136
|
-
|
|
1498
|
+
}
|
|
1137
1499
|
|
|
1138
|
-
|
|
1500
|
+
// Add the primitive objects and metadata.
|
|
1501
|
+
const group = info.group;
|
|
1502
|
+
if ( info.faces.length > 0 ) {
|
|
1139
1503
|
|
|
1140
|
-
|
|
1504
|
+
group.add( createObject( info.faces, 3, false, info.totalFaces ) );
|
|
1141
1505
|
|
|
1142
|
-
|
|
1506
|
+
}
|
|
1143
1507
|
|
|
1144
|
-
|
|
1508
|
+
if ( info.lineSegments.length > 0 ) {
|
|
1145
1509
|
|
|
1146
|
-
|
|
1510
|
+
group.add( createObject( info.lineSegments, 2 ) );
|
|
1147
1511
|
|
|
1148
|
-
|
|
1512
|
+
}
|
|
1149
1513
|
|
|
1150
|
-
|
|
1514
|
+
if ( info.conditionalSegments.length > 0 ) {
|
|
1151
1515
|
|
|
1152
|
-
|
|
1516
|
+
group.add( createObject( info.conditionalSegments, 2, true ) );
|
|
1153
1517
|
|
|
1154
|
-
|
|
1518
|
+
}
|
|
1155
1519
|
|
|
1156
|
-
|
|
1520
|
+
return group;
|
|
1157
1521
|
|
|
1158
|
-
|
|
1522
|
+
}
|
|
1159
1523
|
|
|
1160
|
-
|
|
1161
|
-
finishType = FINISH_TYPE_CHROME;
|
|
1162
|
-
break;
|
|
1524
|
+
hasCachedModel( fileName ) {
|
|
1163
1525
|
|
|
1164
|
-
|
|
1165
|
-
finishType = FINISH_TYPE_PEARLESCENT;
|
|
1166
|
-
break;
|
|
1526
|
+
return fileName !== null && fileName.toLowerCase() in this._cache;
|
|
1167
1527
|
|
|
1168
|
-
|
|
1169
|
-
finishType = FINISH_TYPE_RUBBER;
|
|
1170
|
-
break;
|
|
1528
|
+
}
|
|
1171
1529
|
|
|
1172
|
-
|
|
1173
|
-
finishType = FINISH_TYPE_MATTE_METALLIC;
|
|
1174
|
-
break;
|
|
1530
|
+
async getCachedModel( fileName ) {
|
|
1175
1531
|
|
|
1176
|
-
|
|
1177
|
-
finishType = FINISH_TYPE_METAL;
|
|
1178
|
-
break;
|
|
1532
|
+
if ( fileName !== null && this.hasCachedModel( fileName ) ) {
|
|
1179
1533
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
break;
|
|
1534
|
+
const key = fileName.toLowerCase();
|
|
1535
|
+
const group = await this._cache[ key ];
|
|
1536
|
+
return group.clone();
|
|
1184
1537
|
|
|
1185
|
-
|
|
1186
|
-
throw 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.';
|
|
1187
|
-
break;
|
|
1538
|
+
} else {
|
|
1188
1539
|
|
|
1189
|
-
|
|
1540
|
+
return null;
|
|
1190
1541
|
|
|
1191
1542
|
}
|
|
1192
1543
|
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
switch ( finishType ) {
|
|
1544
|
+
}
|
|
1196
1545
|
|
|
1197
|
-
|
|
1546
|
+
// Loads and parses the model with the given file name. Returns a cached copy if available.
|
|
1547
|
+
async loadModel( fileName ) {
|
|
1198
1548
|
|
|
1199
|
-
|
|
1200
|
-
|
|
1549
|
+
const parseCache = this.parseCache;
|
|
1550
|
+
const key = fileName.toLowerCase();
|
|
1551
|
+
if ( this.hasCachedModel( fileName ) ) {
|
|
1201
1552
|
|
|
1202
|
-
|
|
1553
|
+
// Return cached model if available.
|
|
1554
|
+
return this.getCachedModel( fileName );
|
|
1203
1555
|
|
|
1204
|
-
|
|
1205
|
-
material = new MeshStandardMaterial( { color: colour, roughness: 0.3, metalness: 0.25 } );
|
|
1206
|
-
break;
|
|
1556
|
+
} else {
|
|
1207
1557
|
|
|
1208
|
-
|
|
1558
|
+
// Otherwise parse a new model.
|
|
1559
|
+
// Ensure the file data is loaded and pre parsed.
|
|
1560
|
+
await parseCache.ensureDataLoaded( fileName );
|
|
1209
1561
|
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
break;
|
|
1562
|
+
const info = parseCache.getData( fileName );
|
|
1563
|
+
const promise = this.processIntoMesh( info );
|
|
1213
1564
|
|
|
1214
|
-
|
|
1565
|
+
// Now that the file has loaded it's possible that another part parse has been waiting in parallel
|
|
1566
|
+
// so check the cache again to see if it's been added since the last async operation so we don't
|
|
1567
|
+
// do unnecessary work.
|
|
1568
|
+
if ( this.hasCachedModel( fileName ) ) {
|
|
1215
1569
|
|
|
1216
|
-
|
|
1217
|
-
material = new MeshStandardMaterial( { color: colour, roughness: 0.9, metalness: 0 } );
|
|
1218
|
-
break;
|
|
1570
|
+
return this.getCachedModel( fileName );
|
|
1219
1571
|
|
|
1220
|
-
|
|
1572
|
+
}
|
|
1221
1573
|
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
break;
|
|
1574
|
+
// Cache object if it's a part so it can be reused later.
|
|
1575
|
+
if ( isPartType( info.type ) ) {
|
|
1225
1576
|
|
|
1226
|
-
|
|
1577
|
+
this._cache[ key ] = promise;
|
|
1227
1578
|
|
|
1228
|
-
|
|
1229
|
-
material = new MeshStandardMaterial( { color: colour, roughness: 0.2, metalness: 0.85 } );
|
|
1230
|
-
break;
|
|
1579
|
+
}
|
|
1231
1580
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1581
|
+
// return a copy
|
|
1582
|
+
const group = await promise;
|
|
1583
|
+
return group.clone();
|
|
1235
1584
|
|
|
1236
1585
|
}
|
|
1237
1586
|
|
|
1238
|
-
|
|
1239
|
-
material.premultipliedAlpha = true;
|
|
1240
|
-
material.opacity = alpha;
|
|
1241
|
-
material.depthWrite = ! isTransparent;
|
|
1587
|
+
}
|
|
1242
1588
|
|
|
1243
|
-
|
|
1244
|
-
|
|
1589
|
+
// parses the given model text into a renderable object. Returns cached copy if available.
|
|
1590
|
+
async parseModel( text ) {
|
|
1245
1591
|
|
|
1246
|
-
|
|
1592
|
+
const parseCache = this.parseCache;
|
|
1593
|
+
const info = parseCache.parse( text );
|
|
1594
|
+
if ( isPartType( info.type ) && this.hasCachedModel( info.fileName ) ) {
|
|
1247
1595
|
|
|
1248
|
-
|
|
1596
|
+
return this.getCachedModel( info.fileName );
|
|
1249
1597
|
|
|
1250
1598
|
}
|
|
1251
1599
|
|
|
1252
|
-
|
|
1600
|
+
return this.processIntoMesh( info );
|
|
1253
1601
|
|
|
1254
|
-
|
|
1255
|
-
edgeMaterial = new LineBasicMaterial( {
|
|
1256
|
-
color: edgeColour,
|
|
1257
|
-
transparent: isTransparent,
|
|
1258
|
-
opacity: alpha,
|
|
1259
|
-
depthWrite: ! isTransparent
|
|
1260
|
-
} );
|
|
1261
|
-
edgeMaterial.userData.code = code;
|
|
1262
|
-
edgeMaterial.name = name + ' - Edge';
|
|
1602
|
+
}
|
|
1263
1603
|
|
|
1264
|
-
|
|
1265
|
-
edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial( {
|
|
1604
|
+
}
|
|
1266
1605
|
|
|
1267
|
-
|
|
1268
|
-
transparent: isTransparent,
|
|
1269
|
-
depthWrite: ! isTransparent,
|
|
1270
|
-
color: edgeColour,
|
|
1271
|
-
opacity: alpha,
|
|
1606
|
+
function sortByMaterial( a, b ) {
|
|
1272
1607
|
|
|
1273
|
-
|
|
1608
|
+
if ( a.colorCode === b.colorCode ) {
|
|
1274
1609
|
|
|
1275
|
-
|
|
1610
|
+
return 0;
|
|
1276
1611
|
|
|
1277
|
-
|
|
1278
|
-
material.name = name;
|
|
1612
|
+
}
|
|
1279
1613
|
|
|
1280
|
-
|
|
1614
|
+
if ( a.colorCode < b.colorCode ) {
|
|
1281
1615
|
|
|
1282
|
-
return
|
|
1616
|
+
return - 1;
|
|
1283
1617
|
|
|
1284
1618
|
}
|
|
1285
1619
|
|
|
1286
|
-
|
|
1620
|
+
return 1;
|
|
1287
1621
|
|
|
1288
|
-
|
|
1622
|
+
}
|
|
1289
1623
|
|
|
1290
|
-
|
|
1291
|
-
const currentParseScope = parseScope;
|
|
1292
|
-
const parentParseScope = currentParseScope.parentScope;
|
|
1624
|
+
function createObject( elements, elementSize, isConditionalSegments = false, totalElements = null ) {
|
|
1293
1625
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
const mainEdgeColourCode = currentParseScope.mainEdgeColourCode;
|
|
1626
|
+
// Creates a LineSegments (elementSize = 2) or a Mesh (elementSize = 3 )
|
|
1627
|
+
// With per face / segment material, implemented with mesh groups and materials array
|
|
1297
1628
|
|
|
1629
|
+
// Sort the faces or line segments by color code to make later the mesh groups
|
|
1630
|
+
elements.sort( sortByMaterial );
|
|
1298
1631
|
|
|
1299
|
-
|
|
1300
|
-
let faces;
|
|
1301
|
-
let lineSegments;
|
|
1302
|
-
let conditionalSegments;
|
|
1632
|
+
if ( totalElements === null ) {
|
|
1303
1633
|
|
|
1304
|
-
|
|
1634
|
+
totalElements = elements.length;
|
|
1305
1635
|
|
|
1306
|
-
|
|
1307
|
-
let keywords = null;
|
|
1636
|
+
}
|
|
1308
1637
|
|
|
1309
|
-
|
|
1638
|
+
const positions = new Float32Array( elementSize * totalElements * 3 );
|
|
1639
|
+
const normals = elementSize === 3 ? new Float32Array( elementSize * totalElements * 3 ) : null;
|
|
1640
|
+
const materials = [];
|
|
1310
1641
|
|
|
1311
|
-
|
|
1312
|
-
|
|
1642
|
+
const quadArray = new Array( 6 );
|
|
1643
|
+
const bufferGeometry = new BufferGeometry();
|
|
1644
|
+
let prevMaterial = null;
|
|
1645
|
+
let index0 = 0;
|
|
1646
|
+
let numGroupVerts = 0;
|
|
1647
|
+
let offset = 0;
|
|
1313
1648
|
|
|
1314
|
-
|
|
1649
|
+
for ( let iElem = 0, nElem = elements.length; iElem < nElem; iElem ++ ) {
|
|
1315
1650
|
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1651
|
+
const elem = elements[ iElem ];
|
|
1652
|
+
let vertices = elem.vertices;
|
|
1653
|
+
if ( vertices.length === 4 ) {
|
|
1318
1654
|
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1655
|
+
quadArray[ 0 ] = vertices[ 0 ];
|
|
1656
|
+
quadArray[ 1 ] = vertices[ 1 ];
|
|
1657
|
+
quadArray[ 2 ] = vertices[ 2 ];
|
|
1658
|
+
quadArray[ 3 ] = vertices[ 0 ];
|
|
1659
|
+
quadArray[ 4 ] = vertices[ 2 ];
|
|
1660
|
+
quadArray[ 5 ] = vertices[ 3 ];
|
|
1661
|
+
vertices = quadArray;
|
|
1322
1662
|
|
|
1323
|
-
|
|
1324
|
-
let bfcCCW = true;
|
|
1325
|
-
let bfcInverted = false;
|
|
1326
|
-
let bfcCull = true;
|
|
1327
|
-
let type = '';
|
|
1663
|
+
}
|
|
1328
1664
|
|
|
1329
|
-
let
|
|
1665
|
+
for ( let j = 0, l = vertices.length; j < l; j ++ ) {
|
|
1330
1666
|
|
|
1331
|
-
|
|
1332
|
-
|
|
1667
|
+
const v = vertices[ j ];
|
|
1668
|
+
const index = offset + j * 3;
|
|
1669
|
+
positions[ index + 0 ] = v.x;
|
|
1670
|
+
positions[ index + 1 ] = v.y;
|
|
1671
|
+
positions[ index + 2 ] = v.z;
|
|
1333
1672
|
|
|
1334
|
-
|
|
1673
|
+
}
|
|
1335
1674
|
|
|
1336
|
-
|
|
1675
|
+
// create the normals array if this is a set of faces
|
|
1676
|
+
if ( elementSize === 3 ) {
|
|
1337
1677
|
|
|
1338
|
-
if ( !
|
|
1678
|
+
if ( ! elem.faceNormal ) {
|
|
1339
1679
|
|
|
1340
|
-
|
|
1680
|
+
const v0 = vertices[ 0 ];
|
|
1681
|
+
const v1 = vertices[ 1 ];
|
|
1682
|
+
const v2 = vertices[ 2 ];
|
|
1683
|
+
_tempVec0.subVectors( v1, v0 );
|
|
1684
|
+
_tempVec1.subVectors( v2, v1 );
|
|
1685
|
+
elem.faceNormal = new Vector3()
|
|
1686
|
+
.crossVectors( _tempVec0, _tempVec1 )
|
|
1687
|
+
.normalize();
|
|
1341
1688
|
|
|
1342
1689
|
}
|
|
1343
1690
|
|
|
1344
|
-
|
|
1691
|
+
let elemNormals = elem.normals;
|
|
1692
|
+
if ( elemNormals.length === 4 ) {
|
|
1345
1693
|
|
|
1346
|
-
|
|
1694
|
+
quadArray[ 0 ] = elemNormals[ 0 ];
|
|
1695
|
+
quadArray[ 1 ] = elemNormals[ 1 ];
|
|
1696
|
+
quadArray[ 2 ] = elemNormals[ 2 ];
|
|
1697
|
+
quadArray[ 3 ] = elemNormals[ 0 ];
|
|
1698
|
+
quadArray[ 4 ] = elemNormals[ 2 ];
|
|
1699
|
+
quadArray[ 5 ] = elemNormals[ 3 ];
|
|
1700
|
+
elemNormals = quadArray;
|
|
1347
1701
|
|
|
1348
1702
|
}
|
|
1349
1703
|
|
|
1350
|
-
|
|
1704
|
+
for ( let j = 0, l = elemNormals.length; j < l; j ++ ) {
|
|
1351
1705
|
|
|
1352
|
-
|
|
1706
|
+
// use face normal if a vertex normal is not provided
|
|
1707
|
+
let n = elem.faceNormal;
|
|
1708
|
+
if ( elemNormals[ j ] ) {
|
|
1353
1709
|
|
|
1354
|
-
|
|
1710
|
+
n = elemNormals[ j ].norm;
|
|
1355
1711
|
|
|
1356
|
-
|
|
1712
|
+
}
|
|
1357
1713
|
|
|
1358
|
-
|
|
1714
|
+
const index = offset + j * 3;
|
|
1715
|
+
normals[ index + 0 ] = n.x;
|
|
1716
|
+
normals[ index + 1 ] = n.y;
|
|
1717
|
+
normals[ index + 2 ] = n.z;
|
|
1359
1718
|
|
|
1360
|
-
|
|
1719
|
+
}
|
|
1361
1720
|
|
|
1362
|
-
|
|
1721
|
+
}
|
|
1363
1722
|
|
|
1364
|
-
|
|
1723
|
+
if ( prevMaterial !== elem.colorCode ) {
|
|
1365
1724
|
|
|
1366
|
-
if (
|
|
1725
|
+
if ( prevMaterial !== null ) {
|
|
1367
1726
|
|
|
1368
|
-
|
|
1727
|
+
bufferGeometry.addGroup( index0, numGroupVerts, materials.length - 1 );
|
|
1369
1728
|
|
|
1370
1729
|
}
|
|
1371
1730
|
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
|
-
// Parse all line commands
|
|
1377
|
-
for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) {
|
|
1731
|
+
const material = elem.material;
|
|
1378
1732
|
|
|
1379
|
-
|
|
1733
|
+
if ( material !== null ) {
|
|
1380
1734
|
|
|
1381
|
-
|
|
1735
|
+
if ( elementSize === 3 ) {
|
|
1382
1736
|
|
|
1383
|
-
|
|
1737
|
+
materials.push( material );
|
|
1384
1738
|
|
|
1385
|
-
if (
|
|
1739
|
+
} else if ( elementSize === 2 ) {
|
|
1386
1740
|
|
|
1387
|
-
|
|
1388
|
-
this.cache.setData( currentEmbeddedFileName.toLowerCase(), currentEmbeddedText );
|
|
1741
|
+
if ( isConditionalSegments ) {
|
|
1389
1742
|
|
|
1390
|
-
|
|
1391
|
-
currentEmbeddedFileName = line.substring( 7 );
|
|
1392
|
-
currentEmbeddedText = '';
|
|
1743
|
+
materials.push( material.userData.edgeMaterial.userData.conditionalEdgeMaterial );
|
|
1393
1744
|
|
|
1394
|
-
|
|
1745
|
+
} else {
|
|
1395
1746
|
|
|
1396
|
-
|
|
1747
|
+
materials.push( material.userData.edgeMaterial );
|
|
1748
|
+
|
|
1749
|
+
}
|
|
1397
1750
|
|
|
1398
1751
|
}
|
|
1399
1752
|
|
|
1400
|
-
|
|
1753
|
+
} else {
|
|
1754
|
+
|
|
1755
|
+
// If a material has not been made available yet then keep the color code string in the material array
|
|
1756
|
+
// to save the spot for the material once a parent scopes materials are being applied to the object.
|
|
1757
|
+
materials.push( elem.colorCode );
|
|
1401
1758
|
|
|
1402
1759
|
}
|
|
1403
1760
|
|
|
1404
|
-
|
|
1761
|
+
prevMaterial = elem.colorCode;
|
|
1762
|
+
index0 = offset / 3;
|
|
1763
|
+
numGroupVerts = vertices.length;
|
|
1405
1764
|
|
|
1406
|
-
|
|
1765
|
+
} else {
|
|
1407
1766
|
|
|
1408
|
-
|
|
1767
|
+
numGroupVerts += vertices.length;
|
|
1409
1768
|
|
|
1410
|
-
|
|
1411
|
-
continue;
|
|
1769
|
+
}
|
|
1412
1770
|
|
|
1413
|
-
|
|
1771
|
+
offset += 3 * vertices.length;
|
|
1414
1772
|
|
|
1415
|
-
|
|
1416
|
-
const lineType = lp.getToken();
|
|
1773
|
+
}
|
|
1417
1774
|
|
|
1418
|
-
|
|
1419
|
-
let segment;
|
|
1420
|
-
let inverted;
|
|
1421
|
-
let ccw;
|
|
1422
|
-
let doubleSided;
|
|
1423
|
-
let v0, v1, v2, v3, c0, c1, faceNormal;
|
|
1775
|
+
if ( numGroupVerts > 0 ) {
|
|
1424
1776
|
|
|
1425
|
-
|
|
1777
|
+
bufferGeometry.addGroup( index0, Infinity, materials.length - 1 );
|
|
1426
1778
|
|
|
1427
|
-
|
|
1428
|
-
case '0':
|
|
1779
|
+
}
|
|
1429
1780
|
|
|
1430
|
-
|
|
1431
|
-
const meta = lp.getToken();
|
|
1781
|
+
bufferGeometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
|
|
1432
1782
|
|
|
1433
|
-
|
|
1783
|
+
if ( normals !== null ) {
|
|
1434
1784
|
|
|
1435
|
-
|
|
1785
|
+
bufferGeometry.setAttribute( 'normal', new BufferAttribute( normals, 3 ) );
|
|
1436
1786
|
|
|
1437
|
-
|
|
1787
|
+
}
|
|
1438
1788
|
|
|
1439
|
-
|
|
1789
|
+
let object3d = null;
|
|
1440
1790
|
|
|
1441
|
-
|
|
1791
|
+
if ( elementSize === 2 ) {
|
|
1442
1792
|
|
|
1443
|
-
|
|
1444
|
-
// needs to be flipped.
|
|
1445
|
-
if (
|
|
1446
|
-
currentParseScope.matrix.determinant() < 0 && (
|
|
1447
|
-
scope.separateObjects && isPrimitiveType( type ) ||
|
|
1448
|
-
! scope.separateObjects
|
|
1449
|
-
) ) {
|
|
1793
|
+
if ( isConditionalSegments ) {
|
|
1450
1794
|
|
|
1451
|
-
|
|
1795
|
+
object3d = new ConditionalLineSegments( bufferGeometry, materials.length === 1 ? materials[ 0 ] : materials );
|
|
1452
1796
|
|
|
1453
|
-
|
|
1797
|
+
} else {
|
|
1454
1798
|
|
|
1455
|
-
|
|
1456
|
-
lineSegments = currentParseScope.lineSegments;
|
|
1457
|
-
conditionalSegments = currentParseScope.conditionalSegments;
|
|
1799
|
+
object3d = new LineSegments( bufferGeometry, materials.length === 1 ? materials[ 0 ] : materials );
|
|
1458
1800
|
|
|
1459
|
-
|
|
1801
|
+
}
|
|
1460
1802
|
|
|
1461
|
-
|
|
1803
|
+
} else if ( elementSize === 3 ) {
|
|
1462
1804
|
|
|
1463
|
-
|
|
1464
|
-
if ( material ) {
|
|
1805
|
+
object3d = new Mesh( bufferGeometry, materials.length === 1 ? materials[ 0 ] : materials );
|
|
1465
1806
|
|
|
1466
|
-
|
|
1807
|
+
}
|
|
1467
1808
|
|
|
1468
|
-
|
|
1809
|
+
if ( isConditionalSegments ) {
|
|
1469
1810
|
|
|
1470
|
-
|
|
1811
|
+
object3d.isConditionalLine = true;
|
|
1471
1812
|
|
|
1472
|
-
|
|
1813
|
+
const controlArray0 = new Float32Array( elements.length * 3 * 2 );
|
|
1814
|
+
const controlArray1 = new Float32Array( elements.length * 3 * 2 );
|
|
1815
|
+
const directionArray = new Float32Array( elements.length * 3 * 2 );
|
|
1816
|
+
for ( let i = 0, l = elements.length; i < l; i ++ ) {
|
|
1473
1817
|
|
|
1474
|
-
|
|
1818
|
+
const os = elements[ i ];
|
|
1819
|
+
const vertices = os.vertices;
|
|
1820
|
+
const controlPoints = os.controlPoints;
|
|
1821
|
+
const c0 = controlPoints[ 0 ];
|
|
1822
|
+
const c1 = controlPoints[ 1 ];
|
|
1823
|
+
const v0 = vertices[ 0 ];
|
|
1824
|
+
const v1 = vertices[ 1 ];
|
|
1825
|
+
const index = i * 3 * 2;
|
|
1826
|
+
controlArray0[ index + 0 ] = c0.x;
|
|
1827
|
+
controlArray0[ index + 1 ] = c0.y;
|
|
1828
|
+
controlArray0[ index + 2 ] = c0.z;
|
|
1829
|
+
controlArray0[ index + 3 ] = c0.x;
|
|
1830
|
+
controlArray0[ index + 4 ] = c0.y;
|
|
1831
|
+
controlArray0[ index + 5 ] = c0.z;
|
|
1475
1832
|
|
|
1476
|
-
|
|
1833
|
+
controlArray1[ index + 0 ] = c1.x;
|
|
1834
|
+
controlArray1[ index + 1 ] = c1.y;
|
|
1835
|
+
controlArray1[ index + 2 ] = c1.z;
|
|
1836
|
+
controlArray1[ index + 3 ] = c1.x;
|
|
1837
|
+
controlArray1[ index + 4 ] = c1.y;
|
|
1838
|
+
controlArray1[ index + 5 ] = c1.z;
|
|
1477
1839
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1840
|
+
directionArray[ index + 0 ] = v1.x - v0.x;
|
|
1841
|
+
directionArray[ index + 1 ] = v1.y - v0.y;
|
|
1842
|
+
directionArray[ index + 2 ] = v1.z - v0.z;
|
|
1843
|
+
directionArray[ index + 3 ] = v1.x - v0.x;
|
|
1844
|
+
directionArray[ index + 4 ] = v1.y - v0.y;
|
|
1845
|
+
directionArray[ index + 5 ] = v1.z - v0.z;
|
|
1480
1846
|
|
|
1481
|
-
|
|
1847
|
+
}
|
|
1482
1848
|
|
|
1483
|
-
|
|
1484
|
-
|
|
1849
|
+
bufferGeometry.setAttribute( 'control0', new BufferAttribute( controlArray0, 3, false ) );
|
|
1850
|
+
bufferGeometry.setAttribute( 'control1', new BufferAttribute( controlArray1, 3, false ) );
|
|
1851
|
+
bufferGeometry.setAttribute( 'direction', new BufferAttribute( directionArray, 3, false ) );
|
|
1485
1852
|
|
|
1486
|
-
|
|
1853
|
+
}
|
|
1487
1854
|
|
|
1488
|
-
|
|
1855
|
+
return object3d;
|
|
1489
1856
|
|
|
1490
|
-
|
|
1857
|
+
}
|
|
1491
1858
|
|
|
1492
|
-
|
|
1859
|
+
//
|
|
1493
1860
|
|
|
1494
|
-
|
|
1861
|
+
class LDrawLoader extends Loader {
|
|
1495
1862
|
|
|
1496
|
-
|
|
1863
|
+
constructor( manager ) {
|
|
1497
1864
|
|
|
1498
|
-
|
|
1865
|
+
super( manager );
|
|
1499
1866
|
|
|
1500
|
-
|
|
1867
|
+
// Array of THREE.Material
|
|
1868
|
+
this.materials = [];
|
|
1869
|
+
this.materialLibrary = {};
|
|
1501
1870
|
|
|
1502
|
-
|
|
1871
|
+
// This also allows to handle the embedded text files ("0 FILE" lines)
|
|
1872
|
+
this.partsCache = new LDrawPartsGeometryCache( this );
|
|
1503
1873
|
|
|
1504
|
-
|
|
1874
|
+
// 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.
|
|
1875
|
+
this.fileMap = {};
|
|
1505
1876
|
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
currentEmbeddedFileName = lp.getRemainingString();
|
|
1509
|
-
currentEmbeddedText = '';
|
|
1877
|
+
// Initializes the materials library with default materials
|
|
1878
|
+
this.setMaterials( [] );
|
|
1510
1879
|
|
|
1511
|
-
|
|
1512
|
-
|
|
1880
|
+
// If this flag is set to true the vertex normals will be smoothed.
|
|
1881
|
+
this.smoothNormals = true;
|
|
1513
1882
|
|
|
1514
|
-
|
|
1883
|
+
// The path to load parts from the LDraw parts library from.
|
|
1884
|
+
this.partsLibraryPath = '';
|
|
1515
1885
|
|
|
1516
|
-
|
|
1886
|
+
}
|
|
1517
1887
|
|
|
1518
|
-
|
|
1888
|
+
setPartsLibraryPath( path ) {
|
|
1519
1889
|
|
|
1520
|
-
|
|
1521
|
-
|
|
1890
|
+
this.partsLibraryPath = path;
|
|
1891
|
+
return this;
|
|
1522
1892
|
|
|
1523
|
-
|
|
1893
|
+
}
|
|
1524
1894
|
|
|
1525
|
-
|
|
1895
|
+
async preloadMaterials( url ) {
|
|
1526
1896
|
|
|
1527
|
-
|
|
1528
|
-
|
|
1897
|
+
const fileLoader = new FileLoader( this.manager );
|
|
1898
|
+
fileLoader.setPath( this.path );
|
|
1899
|
+
fileLoader.setRequestHeader( this.requestHeader );
|
|
1900
|
+
fileLoader.setWithCredentials( this.withCredentials );
|
|
1529
1901
|
|
|
1530
|
-
|
|
1531
|
-
|
|
1902
|
+
const text = await fileLoader.loadAsync( url );
|
|
1903
|
+
const colorLineRegex = /^0 !COLOUR/;
|
|
1904
|
+
const lines = text.split( /[\n\r]/g );
|
|
1905
|
+
const materials = [];
|
|
1906
|
+
for ( let i = 0, l = lines.length; i < l; i ++ ) {
|
|
1532
1907
|
|
|
1533
|
-
|
|
1908
|
+
const line = lines[ i ];
|
|
1909
|
+
if ( colorLineRegex.test( line ) ) {
|
|
1534
1910
|
|
|
1535
|
-
|
|
1536
|
-
|
|
1911
|
+
const directive = line.replace( colorLineRegex, '' );
|
|
1912
|
+
const material = this.parseColorMetaDirective( new LineParser( directive ) );
|
|
1913
|
+
materials.push( material );
|
|
1537
1914
|
|
|
1538
|
-
|
|
1915
|
+
}
|
|
1539
1916
|
|
|
1540
|
-
|
|
1917
|
+
}
|
|
1541
1918
|
|
|
1542
|
-
|
|
1919
|
+
this.setMaterials( materials );
|
|
1543
1920
|
|
|
1544
|
-
|
|
1921
|
+
}
|
|
1545
1922
|
|
|
1546
|
-
|
|
1923
|
+
load( url, onLoad, onProgress, onError ) {
|
|
1547
1924
|
|
|
1548
|
-
|
|
1549
|
-
|
|
1925
|
+
const fileLoader = new FileLoader( this.manager );
|
|
1926
|
+
fileLoader.setPath( this.path );
|
|
1927
|
+
fileLoader.setRequestHeader( this.requestHeader );
|
|
1928
|
+
fileLoader.setWithCredentials( this.withCredentials );
|
|
1929
|
+
fileLoader.load( url, text => {
|
|
1550
1930
|
|
|
1551
|
-
|
|
1931
|
+
this.partsCache
|
|
1932
|
+
.parseModel( text, this.materialLibrary )
|
|
1933
|
+
.then( group => {
|
|
1552
1934
|
|
|
1553
|
-
|
|
1935
|
+
this.applyMaterialsToMesh( group, MAIN_COLOUR_CODE, this.materialLibrary, true );
|
|
1936
|
+
this.computeConstructionSteps( group );
|
|
1937
|
+
onLoad( group );
|
|
1554
1938
|
|
|
1555
|
-
|
|
1939
|
+
} )
|
|
1940
|
+
.catch( onError );
|
|
1556
1941
|
|
|
1557
|
-
|
|
1942
|
+
}, onProgress, onError );
|
|
1558
1943
|
|
|
1559
|
-
|
|
1944
|
+
}
|
|
1560
1945
|
|
|
1561
|
-
|
|
1946
|
+
parse( text, onLoad ) {
|
|
1562
1947
|
|
|
1563
|
-
|
|
1948
|
+
this.partsCache
|
|
1949
|
+
.parseModel( text, this.materialLibrary )
|
|
1950
|
+
.then( group => {
|
|
1564
1951
|
|
|
1565
|
-
|
|
1952
|
+
this.computeConstructionSteps( group );
|
|
1953
|
+
onLoad( group );
|
|
1566
1954
|
|
|
1567
|
-
|
|
1955
|
+
} );
|
|
1568
1956
|
|
|
1569
|
-
|
|
1957
|
+
}
|
|
1570
1958
|
|
|
1571
|
-
|
|
1959
|
+
setMaterials( materials ) {
|
|
1572
1960
|
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1961
|
+
this.materialLibrary = {};
|
|
1962
|
+
this.materials = [];
|
|
1963
|
+
for ( let i = 0, l = materials.length; i < l; i ++ ) {
|
|
1576
1964
|
|
|
1577
|
-
|
|
1965
|
+
this.addMaterial( materials[ i ] );
|
|
1578
1966
|
|
|
1579
|
-
|
|
1967
|
+
}
|
|
1580
1968
|
|
|
1581
|
-
|
|
1969
|
+
// Add default main triangle and line edge materials (used in pieces that can be colored with a main color)
|
|
1970
|
+
this.addMaterial( this.parseColorMetaDirective( new LineParser( 'Main_Colour CODE 16 VALUE #FF8080 EDGE #333333' ) ) );
|
|
1971
|
+
this.addMaterial( this.parseColorMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) ) );
|
|
1582
1972
|
|
|
1583
|
-
|
|
1584
|
-
case '1':
|
|
1973
|
+
return this;
|
|
1585
1974
|
|
|
1586
|
-
|
|
1975
|
+
}
|
|
1587
1976
|
|
|
1588
|
-
|
|
1589
|
-
const posY = parseFloat( lp.getToken() );
|
|
1590
|
-
const posZ = parseFloat( lp.getToken() );
|
|
1591
|
-
const m0 = parseFloat( lp.getToken() );
|
|
1592
|
-
const m1 = parseFloat( lp.getToken() );
|
|
1593
|
-
const m2 = parseFloat( lp.getToken() );
|
|
1594
|
-
const m3 = parseFloat( lp.getToken() );
|
|
1595
|
-
const m4 = parseFloat( lp.getToken() );
|
|
1596
|
-
const m5 = parseFloat( lp.getToken() );
|
|
1597
|
-
const m6 = parseFloat( lp.getToken() );
|
|
1598
|
-
const m7 = parseFloat( lp.getToken() );
|
|
1599
|
-
const m8 = parseFloat( lp.getToken() );
|
|
1977
|
+
setFileMap( fileMap ) {
|
|
1600
1978
|
|
|
1601
|
-
|
|
1602
|
-
m0, m1, m2, posX,
|
|
1603
|
-
m3, m4, m5, posY,
|
|
1604
|
-
m6, m7, m8, posZ,
|
|
1605
|
-
0, 0, 0, 1
|
|
1606
|
-
);
|
|
1979
|
+
this.fileMap = fileMap;
|
|
1607
1980
|
|
|
1608
|
-
|
|
1981
|
+
return this;
|
|
1609
1982
|
|
|
1610
|
-
|
|
1983
|
+
}
|
|
1611
1984
|
|
|
1612
|
-
|
|
1613
|
-
fileName = scope.fileMap[ fileName ];
|
|
1985
|
+
addMaterial( material ) {
|
|
1614
1986
|
|
|
1615
|
-
|
|
1987
|
+
// Adds a material to the material library which is on top of the parse scopes stack. And also to the materials array
|
|
1616
1988
|
|
|
1617
|
-
|
|
1618
|
-
|
|
1989
|
+
const matLib = this.materialLibrary;
|
|
1990
|
+
if ( ! matLib[ material.userData.code ] ) {
|
|
1619
1991
|
|
|
1620
|
-
|
|
1992
|
+
this.materials.push( material );
|
|
1993
|
+
matLib[ material.userData.code ] = material;
|
|
1621
1994
|
|
|
1622
|
-
|
|
1995
|
+
}
|
|
1623
1996
|
|
|
1624
|
-
|
|
1997
|
+
return this;
|
|
1625
1998
|
|
|
1626
|
-
|
|
1999
|
+
}
|
|
1627
2000
|
|
|
1628
|
-
|
|
2001
|
+
getMaterial( colorCode ) {
|
|
1629
2002
|
|
|
1630
|
-
|
|
1631
|
-
material: material,
|
|
1632
|
-
matrix: matrix,
|
|
1633
|
-
fileName: fileName,
|
|
1634
|
-
inverted: bfcInverted !== currentParseScope.inverted,
|
|
1635
|
-
startingConstructionStep: startingConstructionStep
|
|
1636
|
-
} );
|
|
2003
|
+
if ( colorCode.startsWith( '0x2' ) ) {
|
|
1637
2004
|
|
|
1638
|
-
|
|
2005
|
+
// Special 'direct' material value (RGB color)
|
|
2006
|
+
const color = colorCode.substring( 3 );
|
|
1639
2007
|
|
|
1640
|
-
|
|
2008
|
+
return this.parseColorMetaDirective( new LineParser( 'Direct_Color_' + color + ' CODE -1 VALUE #' + color + ' EDGE #' + color + '' ) );
|
|
1641
2009
|
|
|
1642
|
-
|
|
1643
|
-
case '2':
|
|
2010
|
+
}
|
|
1644
2011
|
|
|
1645
|
-
|
|
1646
|
-
v0 = parseVector( lp );
|
|
1647
|
-
v1 = parseVector( lp );
|
|
2012
|
+
return this.materialLibrary[ colorCode ] || null;
|
|
1648
2013
|
|
|
1649
|
-
|
|
1650
|
-
material: material.userData.edgeMaterial,
|
|
1651
|
-
colourCode: material.userData.code,
|
|
1652
|
-
v0: v0,
|
|
1653
|
-
v1: v1,
|
|
2014
|
+
}
|
|
1654
2015
|
|
|
1655
|
-
|
|
1656
|
-
|
|
2016
|
+
// Applies the appropriate materials to a prebuilt hierarchy of geometry. Assumes that color codes are present
|
|
2017
|
+
// in the material array if they need to be filled in.
|
|
2018
|
+
applyMaterialsToMesh( group, parentColorCode, materialHierarchy, finalMaterialPass = false ) {
|
|
1657
2019
|
|
|
1658
|
-
|
|
2020
|
+
// find any missing materials as indicated by a color code string and replace it with a material from the current material lib
|
|
2021
|
+
const loader = this;
|
|
2022
|
+
const parentIsPassthrough = parentColorCode === MAIN_COLOUR_CODE;
|
|
2023
|
+
group.traverse( c => {
|
|
1659
2024
|
|
|
1660
|
-
|
|
2025
|
+
if ( c.isMesh || c.isLineSegments ) {
|
|
1661
2026
|
|
|
1662
|
-
|
|
1663
|
-
case '5':
|
|
2027
|
+
if ( Array.isArray( c.material ) ) {
|
|
1664
2028
|
|
|
1665
|
-
|
|
1666
|
-
v0 = parseVector( lp );
|
|
1667
|
-
v1 = parseVector( lp );
|
|
1668
|
-
c0 = parseVector( lp );
|
|
1669
|
-
c1 = parseVector( lp );
|
|
2029
|
+
for ( let i = 0, l = c.material.length; i < l; i ++ ) {
|
|
1670
2030
|
|
|
1671
|
-
|
|
1672
|
-
material: material.userData.edgeMaterial.userData.conditionalEdgeMaterial,
|
|
1673
|
-
colourCode: material.userData.code,
|
|
1674
|
-
vertices: [ v0, v1 ],
|
|
1675
|
-
controlPoints: [ c0, c1 ],
|
|
1676
|
-
};
|
|
2031
|
+
if ( ! c.material[ i ].isMaterial ) {
|
|
1677
2032
|
|
|
1678
|
-
|
|
2033
|
+
c.material[ i ] = getMaterial( c, c.material[ i ] );
|
|
1679
2034
|
|
|
1680
|
-
|
|
2035
|
+
}
|
|
1681
2036
|
|
|
1682
|
-
|
|
1683
|
-
case '3':
|
|
2037
|
+
}
|
|
1684
2038
|
|
|
1685
|
-
|
|
2039
|
+
} else if ( ! c.material.isMaterial ) {
|
|
1686
2040
|
|
|
1687
|
-
|
|
1688
|
-
ccw = bfcCCW !== inverted;
|
|
1689
|
-
doubleSided = ! bfcCertified || ! bfcCull;
|
|
2041
|
+
c.material = getMaterial( c, c.material );
|
|
1690
2042
|
|
|
1691
|
-
|
|
2043
|
+
}
|
|
1692
2044
|
|
|
1693
|
-
|
|
1694
|
-
v1 = parseVector( lp );
|
|
1695
|
-
v2 = parseVector( lp );
|
|
2045
|
+
}
|
|
1696
2046
|
|
|
1697
|
-
|
|
2047
|
+
} );
|
|
1698
2048
|
|
|
1699
|
-
v2 = parseVector( lp );
|
|
1700
|
-
v1 = parseVector( lp );
|
|
1701
|
-
v0 = parseVector( lp );
|
|
1702
2049
|
|
|
1703
|
-
|
|
2050
|
+
// Returns the appropriate material for the object (line or face) given color code. If the code is "pass through"
|
|
2051
|
+
// (24 for lines, 16 for edges) then the pass through color code is used. If that is also pass through then it's
|
|
2052
|
+
// simply returned for the subsequent material application.
|
|
2053
|
+
function getMaterial( c, colorCode ) {
|
|
1704
2054
|
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
.crossVectors( _tempVec0, _tempVec1 )
|
|
1709
|
-
.normalize();
|
|
2055
|
+
// if our parent is a passthrough color code and we don't have the current material color available then
|
|
2056
|
+
// return early.
|
|
2057
|
+
if ( parentIsPassthrough && ! ( colorCode in materialHierarchy ) && ! finalMaterialPass ) {
|
|
1710
2058
|
|
|
1711
|
-
|
|
1712
|
-
material: material,
|
|
1713
|
-
colourCode: material.userData.code,
|
|
1714
|
-
faceNormal: faceNormal,
|
|
1715
|
-
vertices: [ v0, v1, v2 ],
|
|
1716
|
-
normals: [ null, null, null ],
|
|
1717
|
-
} );
|
|
1718
|
-
currentParseScope.totalFaces ++;
|
|
2059
|
+
return colorCode;
|
|
1719
2060
|
|
|
1720
|
-
|
|
2061
|
+
}
|
|
1721
2062
|
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
faceNormal: faceNormal,
|
|
1726
|
-
vertices: [ v2, v1, v0 ],
|
|
1727
|
-
normals: [ null, null, null ],
|
|
1728
|
-
} );
|
|
1729
|
-
currentParseScope.totalFaces ++;
|
|
2063
|
+
const forEdge = c.isLineSegments || c.isConditionalLine;
|
|
2064
|
+
const isPassthrough = ! forEdge && colorCode === MAIN_COLOUR_CODE || forEdge && colorCode === MAIN_EDGE_COLOUR_CODE;
|
|
2065
|
+
if ( isPassthrough ) {
|
|
1730
2066
|
|
|
1731
|
-
|
|
2067
|
+
colorCode = parentColorCode;
|
|
1732
2068
|
|
|
1733
|
-
|
|
2069
|
+
}
|
|
1734
2070
|
|
|
1735
|
-
|
|
1736
|
-
|
|
2071
|
+
let material = null;
|
|
2072
|
+
if ( colorCode in materialHierarchy ) {
|
|
1737
2073
|
|
|
1738
|
-
|
|
2074
|
+
material = materialHierarchy[ colorCode ];
|
|
1739
2075
|
|
|
1740
|
-
|
|
1741
|
-
ccw = bfcCCW !== inverted;
|
|
1742
|
-
doubleSided = ! bfcCertified || ! bfcCull;
|
|
2076
|
+
} else if ( finalMaterialPass ) {
|
|
1743
2077
|
|
|
1744
|
-
|
|
2078
|
+
// see if we can get the final material from from the "getMaterial" function which will attempt to
|
|
2079
|
+
// parse the "direct" colors
|
|
2080
|
+
material = loader.getMaterial( colorCode );
|
|
2081
|
+
if ( material === null ) {
|
|
1745
2082
|
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
v2 = parseVector( lp );
|
|
1749
|
-
v3 = parseVector( lp );
|
|
2083
|
+
// otherwise throw an error if this is final opportunity to set the material
|
|
2084
|
+
throw new Error( `LDrawLoader: Material properties for code ${ colorCode } not available.` );
|
|
1750
2085
|
|
|
1751
|
-
|
|
2086
|
+
}
|
|
1752
2087
|
|
|
1753
|
-
v3 = parseVector( lp );
|
|
1754
|
-
v2 = parseVector( lp );
|
|
1755
|
-
v1 = parseVector( lp );
|
|
1756
|
-
v0 = parseVector( lp );
|
|
1757
2088
|
|
|
1758
|
-
|
|
2089
|
+
} else {
|
|
1759
2090
|
|
|
1760
|
-
|
|
1761
|
-
_tempVec1.subVectors( v2, v1 );
|
|
1762
|
-
faceNormal = new Vector3()
|
|
1763
|
-
.crossVectors( _tempVec0, _tempVec1 )
|
|
1764
|
-
.normalize();
|
|
2091
|
+
return colorCode;
|
|
1765
2092
|
|
|
1766
|
-
|
|
1767
|
-
// account for the doubling of vertices later when smoothing normals.
|
|
1768
|
-
faces.push( {
|
|
1769
|
-
material: material,
|
|
1770
|
-
colourCode: material.userData.code,
|
|
1771
|
-
faceNormal: faceNormal,
|
|
1772
|
-
vertices: [ v0, v1, v2, v3 ],
|
|
1773
|
-
normals: [ null, null, null, null ],
|
|
1774
|
-
} );
|
|
1775
|
-
currentParseScope.totalFaces += 2;
|
|
2093
|
+
}
|
|
1776
2094
|
|
|
1777
|
-
|
|
2095
|
+
if ( c.isLineSegments ) {
|
|
1778
2096
|
|
|
1779
|
-
|
|
1780
|
-
material: material,
|
|
1781
|
-
colourCode: material.userData.code,
|
|
1782
|
-
faceNormal: faceNormal,
|
|
1783
|
-
vertices: [ v3, v2, v1, v0 ],
|
|
1784
|
-
normals: [ null, null, null, null ],
|
|
1785
|
-
} );
|
|
1786
|
-
currentParseScope.totalFaces += 2;
|
|
2097
|
+
material = material.userData.edgeMaterial;
|
|
1787
2098
|
|
|
1788
|
-
|
|
2099
|
+
if ( c.isConditionalLine ) {
|
|
1789
2100
|
|
|
1790
|
-
|
|
2101
|
+
material = material.userData.conditionalEdgeMaterial;
|
|
1791
2102
|
|
|
1792
|
-
|
|
1793
|
-
throw 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.';
|
|
1794
|
-
break;
|
|
2103
|
+
}
|
|
1795
2104
|
|
|
1796
2105
|
}
|
|
1797
2106
|
|
|
1798
|
-
|
|
2107
|
+
return material;
|
|
1799
2108
|
|
|
1800
|
-
|
|
2109
|
+
}
|
|
1801
2110
|
|
|
1802
|
-
|
|
2111
|
+
}
|
|
1803
2112
|
|
|
1804
|
-
|
|
2113
|
+
getMainMaterial() {
|
|
1805
2114
|
|
|
1806
|
-
|
|
1807
|
-
currentParseScope.keywords = keywords;
|
|
1808
|
-
currentParseScope.subobjects = subobjects;
|
|
1809
|
-
currentParseScope.numSubobjects = subobjects.length;
|
|
1810
|
-
currentParseScope.subobjectIndex = 0;
|
|
2115
|
+
return this.getMaterial( MAIN_COLOUR_CODE );
|
|
1811
2116
|
|
|
1812
|
-
|
|
1813
|
-
if ( isRoot || scope.separateObjects && ! isPrimitiveType( type ) ) {
|
|
2117
|
+
}
|
|
1814
2118
|
|
|
1815
|
-
|
|
1816
|
-
currentParseScope.groupObject.userData.startingConstructionStep = currentParseScope.startingConstructionStep;
|
|
2119
|
+
getMainEdgeMaterial() {
|
|
1817
2120
|
|
|
1818
|
-
|
|
2121
|
+
const mainMat = this.getMainMaterial();
|
|
2122
|
+
return mainMat && mainMat.userData ? mainMat.userData.edgeMaterial : null;
|
|
1819
2123
|
|
|
1820
2124
|
}
|
|
1821
2125
|
|
|
1822
|
-
|
|
2126
|
+
parseColorMetaDirective( lineParser ) {
|
|
1823
2127
|
|
|
1824
|
-
//
|
|
2128
|
+
// Parses a color definition and returns a THREE.Material
|
|
1825
2129
|
|
|
1826
|
-
let
|
|
2130
|
+
let code = null;
|
|
1827
2131
|
|
|
1828
|
-
|
|
2132
|
+
// Triangle and line colors
|
|
2133
|
+
let color = 0xFF00FF;
|
|
2134
|
+
let edgeColor = 0xFF00FF;
|
|
1829
2135
|
|
|
1830
|
-
|
|
2136
|
+
// Transparency
|
|
2137
|
+
let alpha = 1;
|
|
2138
|
+
let isTransparent = false;
|
|
2139
|
+
// Self-illumination:
|
|
2140
|
+
let luminance = 0;
|
|
1831
2141
|
|
|
1832
|
-
|
|
2142
|
+
let finishType = FINISH_TYPE_DEFAULT;
|
|
1833
2143
|
|
|
1834
|
-
|
|
2144
|
+
let edgeMaterial = null;
|
|
1835
2145
|
|
|
1836
|
-
|
|
2146
|
+
const name = lineParser.getToken();
|
|
2147
|
+
if ( ! name ) {
|
|
1837
2148
|
|
|
1838
|
-
|
|
2149
|
+
throw new Error( 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.' );
|
|
2150
|
+
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
// Parse tag tokens and their parameters
|
|
2154
|
+
let token = null;
|
|
2155
|
+
while ( true ) {
|
|
2156
|
+
|
|
2157
|
+
token = lineParser.getToken();
|
|
2158
|
+
|
|
2159
|
+
if ( ! token ) {
|
|
2160
|
+
|
|
2161
|
+
break;
|
|
1839
2162
|
|
|
1840
2163
|
}
|
|
1841
2164
|
|
|
1842
|
-
|
|
2165
|
+
switch ( token.toUpperCase() ) {
|
|
1843
2166
|
|
|
1844
|
-
|
|
2167
|
+
case 'CODE':
|
|
1845
2168
|
|
|
1846
|
-
|
|
2169
|
+
code = lineParser.getToken();
|
|
2170
|
+
break;
|
|
1847
2171
|
|
|
1848
|
-
|
|
2172
|
+
case 'VALUE':
|
|
1849
2173
|
|
|
1850
|
-
|
|
1851
|
-
|
|
2174
|
+
color = lineParser.getToken();
|
|
2175
|
+
if ( color.startsWith( '0x' ) ) {
|
|
1852
2176
|
|
|
1853
|
-
|
|
2177
|
+
color = '#' + color.substring( 2 );
|
|
1854
2178
|
|
|
1855
|
-
|
|
2179
|
+
} else if ( ! color.startsWith( '#' ) ) {
|
|
1856
2180
|
|
|
1857
|
-
|
|
2181
|
+
throw new Error( 'LDrawLoader: Invalid color while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
1858
2182
|
|
|
1859
|
-
|
|
1860
|
-
// is added directly into the parent model (meaning it will never get smoothed by
|
|
1861
|
-
// being added to a part)
|
|
1862
|
-
const doSmooth =
|
|
1863
|
-
isPartType( subobjectParseScope.type ) ||
|
|
1864
|
-
(
|
|
1865
|
-
! isPartType( subobjectParseScope.type ) &&
|
|
1866
|
-
! isModelType( subobjectParseScope.type ) &&
|
|
1867
|
-
isModelType( subobjectParseScope.parentScope.type )
|
|
1868
|
-
);
|
|
2183
|
+
}
|
|
1869
2184
|
|
|
1870
|
-
|
|
2185
|
+
break;
|
|
1871
2186
|
|
|
1872
|
-
|
|
2187
|
+
case 'EDGE':
|
|
1873
2188
|
|
|
1874
|
-
|
|
2189
|
+
edgeColor = lineParser.getToken();
|
|
2190
|
+
if ( edgeColor.startsWith( '0x' ) ) {
|
|
1875
2191
|
|
|
1876
|
-
|
|
1877
|
-
if ( this.separateObjects && ! isPrimitiveType( subobjectParseScope.type ) || isRoot ) {
|
|
2192
|
+
edgeColor = '#' + edgeColor.substring( 2 );
|
|
1878
2193
|
|
|
1879
|
-
|
|
2194
|
+
} else if ( ! edgeColor.startsWith( '#' ) ) {
|
|
1880
2195
|
|
|
1881
|
-
|
|
2196
|
+
// Try to see if edge color is a color code
|
|
2197
|
+
edgeMaterial = this.getMaterial( edgeColor );
|
|
2198
|
+
if ( ! edgeMaterial ) {
|
|
1882
2199
|
|
|
1883
|
-
|
|
2200
|
+
throw new Error( 'LDrawLoader: Invalid edge color while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
1884
2201
|
|
|
1885
|
-
|
|
2202
|
+
}
|
|
1886
2203
|
|
|
1887
|
-
|
|
2204
|
+
// Get the edge material for this triangle material
|
|
2205
|
+
edgeMaterial = edgeMaterial.userData.edgeMaterial;
|
|
1888
2206
|
|
|
1889
|
-
|
|
2207
|
+
}
|
|
1890
2208
|
|
|
1891
|
-
|
|
2209
|
+
break;
|
|
1892
2210
|
|
|
1893
|
-
|
|
2211
|
+
case 'ALPHA':
|
|
1894
2212
|
|
|
1895
|
-
|
|
2213
|
+
alpha = parseInt( lineParser.getToken() );
|
|
1896
2214
|
|
|
1897
|
-
|
|
2215
|
+
if ( isNaN( alpha ) ) {
|
|
1898
2216
|
|
|
1899
|
-
|
|
2217
|
+
throw new Error( 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.' );
|
|
1900
2218
|
|
|
1901
|
-
|
|
1902
|
-
objGroup.userData.category = subobjectParseScope.category;
|
|
1903
|
-
objGroup.userData.keywords = subobjectParseScope.keywords;
|
|
1904
|
-
subobjectParseScope.matrix.decompose( objGroup.position, objGroup.quaternion, objGroup.scale );
|
|
2219
|
+
}
|
|
1905
2220
|
|
|
1906
|
-
|
|
2221
|
+
alpha = Math.max( 0, Math.min( 1, alpha / 255 ) );
|
|
1907
2222
|
|
|
1908
|
-
|
|
2223
|
+
if ( alpha < 1 ) {
|
|
1909
2224
|
|
|
1910
|
-
|
|
2225
|
+
isTransparent = true;
|
|
1911
2226
|
|
|
1912
|
-
|
|
1913
|
-
const parentLineSegments = parentParseScope.lineSegments;
|
|
1914
|
-
const parentConditionalSegments = parentParseScope.conditionalSegments;
|
|
1915
|
-
const parentFaces = parentParseScope.faces;
|
|
2227
|
+
}
|
|
1916
2228
|
|
|
1917
|
-
|
|
1918
|
-
const conditionalSegments = subobjectParseScope.conditionalSegments;
|
|
1919
|
-
const faces = subobjectParseScope.faces;
|
|
2229
|
+
break;
|
|
1920
2230
|
|
|
1921
|
-
|
|
2231
|
+
case 'LUMINANCE':
|
|
1922
2232
|
|
|
1923
|
-
|
|
2233
|
+
luminance = parseInt( lineParser.getToken() );
|
|
1924
2234
|
|
|
1925
|
-
|
|
2235
|
+
if ( isNaN( luminance ) ) {
|
|
1926
2236
|
|
|
1927
|
-
|
|
1928
|
-
vertices[ 0 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1929
|
-
vertices[ 1 ].applyMatrix4( subobjectParseScope.matrix );
|
|
2237
|
+
throw new Error( 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.' );
|
|
1930
2238
|
|
|
1931
|
-
|
|
2239
|
+
}
|
|
1932
2240
|
|
|
1933
|
-
|
|
2241
|
+
luminance = Math.max( 0, Math.min( 1, luminance / 255 ) );
|
|
1934
2242
|
|
|
1935
|
-
|
|
2243
|
+
break;
|
|
1936
2244
|
|
|
1937
|
-
|
|
2245
|
+
case 'CHROME':
|
|
2246
|
+
finishType = FINISH_TYPE_CHROME;
|
|
2247
|
+
break;
|
|
1938
2248
|
|
|
1939
|
-
|
|
2249
|
+
case 'PEARLESCENT':
|
|
2250
|
+
finishType = FINISH_TYPE_PEARLESCENT;
|
|
2251
|
+
break;
|
|
1940
2252
|
|
|
1941
|
-
|
|
2253
|
+
case 'RUBBER':
|
|
2254
|
+
finishType = FINISH_TYPE_RUBBER;
|
|
2255
|
+
break;
|
|
1942
2256
|
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
vertices[ 1 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1947
|
-
controlPoints[ 0 ].applyMatrix4( subobjectParseScope.matrix );
|
|
1948
|
-
controlPoints[ 1 ].applyMatrix4( subobjectParseScope.matrix );
|
|
2257
|
+
case 'MATTE_METALLIC':
|
|
2258
|
+
finishType = FINISH_TYPE_MATTE_METALLIC;
|
|
2259
|
+
break;
|
|
1949
2260
|
|
|
1950
|
-
|
|
2261
|
+
case 'METAL':
|
|
2262
|
+
finishType = FINISH_TYPE_METAL;
|
|
2263
|
+
break;
|
|
2264
|
+
|
|
2265
|
+
case 'MATERIAL':
|
|
2266
|
+
// Not implemented
|
|
2267
|
+
lineParser.setToEnd();
|
|
2268
|
+
break;
|
|
1951
2269
|
|
|
1952
|
-
|
|
2270
|
+
default:
|
|
2271
|
+
throw new Error( 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
1953
2272
|
|
|
1954
2273
|
}
|
|
1955
2274
|
|
|
1956
|
-
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
let material = null;
|
|
1957
2278
|
|
|
1958
|
-
|
|
2279
|
+
switch ( finishType ) {
|
|
1959
2280
|
|
|
1960
|
-
|
|
2281
|
+
case FINISH_TYPE_DEFAULT:
|
|
1961
2282
|
|
|
1962
|
-
|
|
1963
|
-
|
|
2283
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0.3, metalness: 0 } );
|
|
2284
|
+
break;
|
|
1964
2285
|
|
|
1965
|
-
|
|
2286
|
+
case FINISH_TYPE_PEARLESCENT:
|
|
1966
2287
|
|
|
1967
|
-
|
|
2288
|
+
// Try to imitate pearlescency by making the surface glossy
|
|
2289
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0.3, metalness: 0.25 } );
|
|
2290
|
+
break;
|
|
1968
2291
|
|
|
1969
|
-
|
|
1970
|
-
_tempVec1.subVectors( vertices[ 2 ], vertices[ 1 ] );
|
|
1971
|
-
tri.faceNormal.crossVectors( _tempVec0, _tempVec1 ).normalize();
|
|
2292
|
+
case FINISH_TYPE_CHROME:
|
|
1972
2293
|
|
|
1973
|
-
|
|
2294
|
+
// Mirror finish surface
|
|
2295
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0, metalness: 1 } );
|
|
2296
|
+
break;
|
|
1974
2297
|
|
|
1975
|
-
|
|
2298
|
+
case FINISH_TYPE_RUBBER:
|
|
1976
2299
|
|
|
1977
|
-
|
|
2300
|
+
// Rubber finish
|
|
2301
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0.9, metalness: 0 } );
|
|
2302
|
+
break;
|
|
1978
2303
|
|
|
1979
|
-
|
|
2304
|
+
case FINISH_TYPE_MATTE_METALLIC:
|
|
1980
2305
|
|
|
1981
|
-
|
|
2306
|
+
// Brushed metal finish
|
|
2307
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0.8, metalness: 0.4 } );
|
|
2308
|
+
break;
|
|
1982
2309
|
|
|
1983
|
-
|
|
2310
|
+
case FINISH_TYPE_METAL:
|
|
2311
|
+
|
|
2312
|
+
// Average metal finish
|
|
2313
|
+
material = new MeshStandardMaterial( { color: color, roughness: 0.2, metalness: 0.85 } );
|
|
2314
|
+
break;
|
|
1984
2315
|
|
|
1985
|
-
|
|
2316
|
+
default:
|
|
2317
|
+
// Should not happen
|
|
2318
|
+
break;
|
|
1986
2319
|
|
|
1987
|
-
|
|
2320
|
+
}
|
|
1988
2321
|
|
|
1989
|
-
|
|
1990
|
-
|
|
2322
|
+
material.transparent = isTransparent;
|
|
2323
|
+
material.premultipliedAlpha = true;
|
|
2324
|
+
material.opacity = alpha;
|
|
2325
|
+
material.depthWrite = ! isTransparent;
|
|
2326
|
+
material.color.convertSRGBToLinear();
|
|
1991
2327
|
|
|
1992
|
-
|
|
2328
|
+
material.polygonOffset = true;
|
|
2329
|
+
material.polygonOffsetFactor = 1;
|
|
1993
2330
|
|
|
1994
|
-
|
|
1995
|
-
if ( subobject ) {
|
|
2331
|
+
if ( luminance !== 0 ) {
|
|
1996
2332
|
|
|
1997
|
-
|
|
1998
|
-
parseScope.matrix.copy( subobject.matrix );
|
|
1999
|
-
parseScope.inverted = subobject.inverted;
|
|
2000
|
-
parseScope.startingConstructionStep = subobject.startingConstructionStep;
|
|
2001
|
-
parseScope.mainColourCode = subobject.material.userData.code;
|
|
2002
|
-
parseScope.mainEdgeColourCode = subobject.material.userData.edgeMaterial.userData.code;
|
|
2003
|
-
parseScope.fileName = subobject.fileName;
|
|
2333
|
+
material.emissive.set( material.color ).multiplyScalar( luminance );
|
|
2004
2334
|
|
|
2005
2335
|
}
|
|
2006
2336
|
|
|
2007
|
-
|
|
2008
|
-
|
|
2337
|
+
if ( ! edgeMaterial ) {
|
|
2338
|
+
|
|
2339
|
+
// This is the material used for edges
|
|
2340
|
+
edgeMaterial = new LineBasicMaterial( {
|
|
2341
|
+
color: edgeColor,
|
|
2342
|
+
transparent: isTransparent,
|
|
2343
|
+
opacity: alpha,
|
|
2344
|
+
depthWrite: ! isTransparent
|
|
2345
|
+
} );
|
|
2346
|
+
edgeMaterial.userData.code = code;
|
|
2347
|
+
edgeMaterial.name = name + ' - Edge';
|
|
2348
|
+
edgeMaterial.color.convertSRGBToLinear();
|
|
2349
|
+
|
|
2350
|
+
// This is the material used for conditional edges
|
|
2351
|
+
edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial( {
|
|
2009
2352
|
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2353
|
+
fog: true,
|
|
2354
|
+
transparent: isTransparent,
|
|
2355
|
+
depthWrite: ! isTransparent,
|
|
2356
|
+
color: edgeColor,
|
|
2357
|
+
opacity: alpha,
|
|
2013
2358
|
|
|
2014
|
-
|
|
2359
|
+
} );
|
|
2360
|
+
edgeMaterial.userData.conditionalEdgeMaterial.color.convertSRGBToLinear();
|
|
2015
2361
|
|
|
2016
2362
|
}
|
|
2017
2363
|
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
const subobjectScopes = await Promise.all( promises );
|
|
2021
|
-
for ( let i = 0, l = subobjectScopes.length; i < l; i ++ ) {
|
|
2364
|
+
material.userData.code = code;
|
|
2365
|
+
material.name = name;
|
|
2022
2366
|
|
|
2023
|
-
|
|
2367
|
+
material.userData.edgeMaterial = edgeMaterial;
|
|
2024
2368
|
|
|
2025
|
-
|
|
2369
|
+
this.addMaterial( material );
|
|
2026
2370
|
|
|
2027
|
-
|
|
2028
|
-
if ( ! parentParseScope.isFromParse ) {
|
|
2371
|
+
return material;
|
|
2029
2372
|
|
|
2030
|
-
|
|
2031
|
-
this.computeConstructionSteps( parseScope.groupObject );
|
|
2373
|
+
}
|
|
2032
2374
|
|
|
2033
|
-
|
|
2375
|
+
computeConstructionSteps( model ) {
|
|
2034
2376
|
|
|
2035
|
-
|
|
2377
|
+
// Sets userdata.constructionStep number in Group objects and userData.numConstructionSteps number in the root Group object.
|
|
2036
2378
|
|
|
2037
|
-
|
|
2379
|
+
let stepNumber = 0;
|
|
2038
2380
|
|
|
2039
|
-
|
|
2381
|
+
model.traverse( c => {
|
|
2040
2382
|
|
|
2041
|
-
|
|
2383
|
+
if ( c.isGroup ) {
|
|
2042
2384
|
|
|
2043
|
-
|
|
2385
|
+
if ( c.userData.startingConstructionStep ) {
|
|
2044
2386
|
|
|
2045
|
-
|
|
2046
|
-
return null;
|
|
2387
|
+
stepNumber ++;
|
|
2047
2388
|
|
|
2048
|
-
|
|
2389
|
+
}
|
|
2049
2390
|
|
|
2050
|
-
|
|
2391
|
+
c.userData.constructionStep = stepNumber;
|
|
2392
|
+
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
} );
|
|
2396
|
+
|
|
2397
|
+
model.userData.numConstructionSteps = stepNumber + 1;
|
|
2051
2398
|
|
|
2052
2399
|
}
|
|
2053
2400
|
|