super-three 0.141.0 → 0.147.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/README.md +9 -9
- package/build/three.cjs +2441 -1569
- package/build/three.js +2441 -1569
- package/build/three.min.js +1 -1
- package/build/three.module.js +2847 -1576
- package/examples/js/animation/AnimationClipCreator.js +0 -8
- package/examples/js/animation/CCDIKSolver.js +50 -67
- package/examples/js/animation/MMDAnimationHelper.js +66 -137
- package/examples/js/animation/MMDPhysics.js +71 -150
- package/examples/js/cameras/CinematicCamera.js +33 -22
- package/examples/js/controls/ArcballControls.js +149 -403
- package/examples/js/controls/DragControls.js +8 -33
- package/examples/js/controls/FirstPersonControls.js +32 -61
- package/examples/js/controls/FlyControls.js +29 -63
- package/examples/js/controls/OrbitControls.js +125 -103
- package/examples/js/controls/PointerLockControls.js +5 -22
- package/examples/js/controls/TrackballControls.js +33 -88
- package/examples/js/controls/TransformControls.js +101 -182
- package/examples/js/csm/CSM.js +4 -39
- package/examples/js/csm/CSMFrustum.js +3 -9
- package/examples/js/csm/CSMHelper.js +24 -4
- package/examples/js/csm/CSMShader.js +2 -6
- package/examples/js/curves/CurveExtras.js +27 -27
- package/examples/js/curves/NURBSCurve.js +4 -16
- package/examples/js/curves/NURBSSurface.js +3 -9
- package/examples/js/curves/NURBSUtils.js +8 -45
- package/examples/js/effects/AnaglyphEffect.js +6 -20
- package/examples/js/effects/AsciiEffect.js +32 -31
- package/examples/js/effects/OutlineEffect.js +30 -54
- package/examples/js/effects/ParallaxBarrierEffect.js +2 -15
- package/examples/js/effects/PeppersGhostEffect.js +14 -41
- package/examples/js/effects/StereoEffect.js +2 -6
- package/examples/js/environments/RoomEnvironment.js +32 -8
- package/examples/js/exporters/ColladaExporter.js +52 -78
- package/examples/js/exporters/DRACOExporter.js +22 -34
- package/examples/js/exporters/EXRExporter.js +15 -18
- package/examples/js/exporters/GLTFExporter.js +168 -345
- package/examples/js/exporters/MMDExporter.js +5 -12
- package/examples/js/exporters/OBJExporter.js +40 -52
- package/examples/js/exporters/PLYExporter.js +50 -57
- package/examples/js/exporters/STLExporter.js +5 -14
- package/examples/js/exporters/USDZExporter.js +119 -27
- package/examples/js/geometries/BoxLineGeometry.js +0 -1
- package/examples/js/geometries/ConvexGeometry.js +12 -7
- package/examples/js/geometries/DecalGeometry.js +53 -20
- package/examples/js/geometries/LightningStrike.js +54 -67
- package/examples/js/geometries/ParametricGeometries.js +8 -7
- package/examples/js/geometries/ParametricGeometry.js +23 -17
- package/examples/js/geometries/RoundedBoxGeometry.js +21 -19
- package/examples/js/geometries/TeapotGeometry.js +54 -50
- package/examples/js/geometries/TextGeometry.js +6 -4
- package/examples/js/helpers/LightProbeHelper.js +1 -2
- package/examples/js/helpers/OctreeHelper.js +22 -20
- package/examples/js/helpers/PositionalAudioHelper.js +8 -6
- package/examples/js/helpers/RectAreaLightHelper.js +6 -7
- package/examples/js/helpers/VertexNormalsHelper.js +15 -13
- package/examples/js/helpers/VertexTangentsHelper.js +15 -9
- package/examples/js/helpers/ViewHelper.js +31 -16
- package/examples/js/interactive/HTMLMesh.js +25 -39
- package/examples/js/interactive/InteractiveGroup.js +9 -14
- package/examples/js/interactive/SelectionBox.js +3 -70
- package/examples/js/interactive/SelectionHelper.js +2 -8
- package/examples/js/libs/ktx-parse.umd.js +1 -0
- package/examples/js/libs/meshopt_decoder.js +98 -32
- package/examples/js/lights/LightProbeGenerator.js +32 -39
- package/examples/js/lights/RectAreaLightUniformsLib.js +5 -1
- package/examples/js/lines/LineGeometry.js +3 -5
- package/examples/js/lines/LineMaterial.js +4 -11
- package/examples/js/lines/LineSegments2.js +40 -89
- package/examples/js/lines/LineSegmentsGeometry.js +7 -28
- package/examples/js/lines/Wireframe.js +2 -7
- package/examples/js/lines/WireframeGeometry2.js +3 -1
- package/examples/js/loaders/3DMLoader.js +58 -155
- package/examples/js/loaders/3MFLoader.js +72 -106
- package/examples/js/loaders/AMFLoader.js +0 -25
- package/examples/js/loaders/BVHLoader.js +44 -43
- package/examples/js/loaders/BasisTextureLoader.js +16 -46
- package/examples/js/loaders/ColladaLoader.js +229 -359
- package/examples/js/loaders/DDSLoader.js +24 -25
- package/examples/js/loaders/DRACOLoader.js +30 -90
- package/examples/js/loaders/EXRLoader.js +69 -177
- package/examples/js/loaders/FBXLoader.js +294 -441
- package/examples/js/loaders/FontLoader.js +9 -31
- package/examples/js/loaders/GCodeLoader.js +15 -16
- package/examples/js/loaders/GLTFLoader.js +458 -739
- package/examples/js/loaders/HDRCubeTextureLoader.js +0 -17
- package/examples/js/loaders/KMZLoader.js +3 -7
- package/examples/js/loaders/KTXLoader.js +12 -30
- package/examples/js/loaders/LDrawLoader.js +309 -355
- package/examples/js/loaders/LUT3dlLoader.js +7 -11
- package/examples/js/loaders/LUTCubeLoader.js +0 -8
- package/examples/js/loaders/LWOLoader.js +59 -124
- package/examples/js/loaders/LogLuvLoader.js +27 -77
- package/examples/js/loaders/LottieLoader.js +4 -4
- package/examples/js/loaders/MD2Loader.js +26 -27
- package/examples/js/loaders/MDDLoader.js +6 -10
- package/examples/js/loaders/MMDLoader.js +180 -189
- package/examples/js/loaders/MTLLoader.js +18 -47
- package/examples/js/loaders/NRRDLoader.js +44 -84
- package/examples/js/loaders/OBJLoader.js +56 -77
- package/examples/js/loaders/PCDLoader.js +92 -42
- package/examples/js/loaders/PDBLoader.js +17 -13
- package/examples/js/loaders/PLYLoader.js +65 -51
- package/examples/js/loaders/PRWMLoader.js +11 -22
- package/examples/js/loaders/PVRLoader.js +7 -16
- package/examples/js/loaders/RGBELoader.js +36 -61
- package/examples/js/loaders/RGBMLoader.js +26 -87
- package/examples/js/loaders/STLLoader.js +20 -27
- package/examples/js/loaders/SVGLoader.js +365 -236
- package/examples/js/loaders/TDSLoader.js +81 -118
- package/examples/js/loaders/TGALoader.js +39 -41
- package/examples/js/loaders/TIFFLoader.js +30 -0
- package/examples/js/loaders/TTFLoader.js +0 -8
- package/examples/js/loaders/TiltLoader.js +14 -15
- package/examples/js/loaders/VOXLoader.js +8 -16
- package/examples/js/loaders/VRMLLoader.js +266 -354
- package/examples/js/loaders/VTKLoader.js +102 -119
- package/examples/js/loaders/XYZLoader.js +2 -4
- package/examples/js/loaders/lwo/IFFParser.js +55 -136
- package/examples/js/loaders/lwo/LWO2Parser.js +39 -89
- package/examples/js/loaders/lwo/LWO3Parser.js +38 -79
- package/examples/js/materials/MeshGouraudMaterial.js +387 -0
- package/examples/js/math/Capsule.js +0 -17
- package/examples/js/math/ColorConverter.js +3 -53
- package/examples/js/math/ConvexHull.js +185 -141
- package/examples/js/math/ImprovedNoise.js +1 -1
- package/examples/js/math/Lut.js +8 -15
- package/examples/js/math/MeshSurfaceSampler.js +6 -28
- package/examples/js/math/OBB.js +90 -49
- package/examples/js/math/Octree.js +2 -57
- package/examples/js/math/SimplexNoise.js +74 -88
- package/examples/js/misc/ConvexObjectBreaker.js +37 -48
- package/examples/js/misc/GPUComputationRenderer.js +47 -14
- package/examples/js/misc/Gyroscope.js +5 -9
- package/examples/js/misc/MD2Character.js +14 -23
- package/examples/js/misc/MD2CharacterComplex.js +73 -54
- package/examples/js/misc/MorphAnimMesh.js +0 -6
- package/examples/js/misc/MorphBlendMesh.js +3 -30
- package/examples/js/misc/ProgressiveLightMap.js +47 -43
- package/examples/js/misc/RollerCoaster.js +17 -24
- package/examples/js/misc/TubePainter.js +18 -12
- package/examples/js/misc/Volume.js +173 -194
- package/examples/js/misc/VolumeSlice.js +91 -99
- package/examples/js/modifiers/CurveModifier.js +19 -21
- package/examples/js/modifiers/EdgeSplitModifier.js +0 -30
- package/examples/js/modifiers/SimplifyModifier.js +57 -60
- package/examples/js/modifiers/TessellateModifier.js +2 -9
- package/examples/js/objects/GroundProjectedEnv.js +181 -0
- package/examples/js/objects/Lensflare.js +47 -38
- package/examples/js/objects/LightningStorm.js +10 -13
- package/examples/js/objects/MarchingCubes.js +80 -59
- package/examples/js/objects/Reflector.js +31 -22
- package/examples/js/objects/ReflectorForSSRPass.js +20 -25
- package/examples/js/objects/Refractor.js +61 -33
- package/examples/js/objects/ShadowMesh.js +6 -3
- package/examples/js/objects/Sky.js +2 -7
- package/examples/js/objects/Water.js +23 -18
- package/examples/js/objects/Water2.js +20 -19
- package/examples/js/physics/AmmoPhysics.js +23 -20
- package/examples/js/physics/OimoPhysics.js +19 -17
- package/examples/js/postprocessing/AdaptiveToneMappingPass.js +13 -20
- package/examples/js/postprocessing/AfterimagePass.js +19 -12
- package/examples/js/postprocessing/BloomPass.js +38 -17
- package/examples/js/postprocessing/BokehPass.js +29 -12
- package/examples/js/postprocessing/ClearPass.js +1 -6
- package/examples/js/postprocessing/CubeTexturePass.js +12 -9
- package/examples/js/postprocessing/DotScreenPass.js +7 -5
- package/examples/js/postprocessing/EffectComposer.js +25 -32
- package/examples/js/postprocessing/FilmPass.js +7 -5
- package/examples/js/postprocessing/GlitchPass.js +10 -11
- package/examples/js/postprocessing/HalftonePass.js +9 -9
- package/examples/js/postprocessing/LUTPass.js +2 -15
- package/examples/js/postprocessing/MaskPass.js +20 -17
- package/examples/js/postprocessing/OutlinePass.js +49 -38
- package/examples/js/postprocessing/Pass.js +11 -14
- package/examples/js/postprocessing/RenderPass.js +3 -7
- package/examples/js/postprocessing/RenderPixelatedPass.js +215 -0
- package/examples/js/postprocessing/SAOPass.js +40 -32
- package/examples/js/postprocessing/SMAAPass.js +34 -17
- package/examples/js/postprocessing/SSAARenderPass.js +14 -14
- package/examples/js/postprocessing/SSAOPass.js +56 -42
- package/examples/js/postprocessing/SSRPass.js +78 -61
- package/examples/js/postprocessing/SavePass.js +14 -6
- package/examples/js/postprocessing/ShaderPass.js +9 -8
- package/examples/js/postprocessing/TAARenderPass.js +11 -9
- package/examples/js/postprocessing/TexturePass.js +7 -4
- package/examples/js/postprocessing/UnrealBloomPass.js +43 -25
- package/examples/js/renderers/CSS2DRenderer.js +4 -23
- package/examples/js/renderers/CSS3DRenderer.js +5 -26
- package/examples/js/renderers/Projector.js +31 -108
- package/examples/js/renderers/SVGRenderer.js +4 -50
- package/examples/js/shaders/ACESFilmicToneMappingShader.js +3 -6
- package/examples/js/shaders/AfterimageShader.js +3 -6
- package/examples/js/shaders/BasicShader.js +3 -6
- package/examples/js/shaders/BleachBypassShader.js +3 -6
- package/examples/js/shaders/BlendShader.js +3 -6
- package/examples/js/shaders/BokehShader.js +3 -6
- package/examples/js/shaders/BokehShader2.js +4 -13
- package/examples/js/shaders/BrightnessContrastShader.js +3 -6
- package/examples/js/shaders/ColorCorrectionShader.js +2 -6
- package/examples/js/shaders/ColorifyShader.js +2 -6
- package/examples/js/shaders/ConvolutionShader.js +5 -10
- package/examples/js/shaders/CopyShader.js +3 -6
- package/examples/js/shaders/DOFMipMapShader.js +3 -6
- package/examples/js/shaders/DepthLimitedBlurShader.js +2 -9
- package/examples/js/shaders/DigitalGlitch.js +3 -6
- package/examples/js/shaders/DotScreenShader.js +2 -6
- package/examples/js/shaders/FXAAShader.js +1 -3
- package/examples/js/shaders/FilmShader.js +3 -6
- package/examples/js/shaders/FocusShader.js +3 -6
- package/examples/js/shaders/FreiChenShader.js +2 -6
- package/examples/js/shaders/GammaCorrectionShader.js +3 -6
- package/examples/js/shaders/GodRaysShader.js +11 -24
- package/examples/js/shaders/HalftoneShader.js +3 -6
- package/examples/js/shaders/HorizontalBlurShader.js +3 -6
- package/examples/js/shaders/HorizontalTiltShiftShader.js +3 -6
- package/examples/js/shaders/HueSaturationShader.js +3 -6
- package/examples/js/shaders/KaleidoShader.js +3 -6
- package/examples/js/shaders/LuminosityHighPassShader.js +2 -6
- package/examples/js/shaders/LuminosityShader.js +4 -7
- package/examples/js/shaders/MMDToonShader.js +2 -4
- package/examples/js/shaders/MirrorShader.js +3 -6
- package/examples/js/shaders/NormalMapShader.js +2 -6
- package/examples/js/shaders/RGBShiftShader.js +3 -6
- package/examples/js/shaders/SAOShader.js +2 -6
- package/examples/js/shaders/SMAAShader.js +6 -18
- package/examples/js/shaders/SSAOShader.js +2 -6
- package/examples/js/shaders/SSRShader.js +6 -18
- package/examples/js/shaders/SepiaShader.js +3 -6
- package/examples/js/shaders/SobelOperatorShader.js +2 -6
- package/examples/js/shaders/TechnicolorShader.js +3 -6
- package/examples/js/shaders/ToneMapShader.js +4 -7
- package/examples/js/shaders/ToonShader.js +8 -24
- package/examples/js/shaders/TriangleBlurShader.js +2 -6
- package/examples/js/shaders/UnpackDepthRGBAShader.js +3 -6
- package/examples/js/shaders/VelocityShader.js +126 -0
- package/examples/js/shaders/VerticalBlurShader.js +3 -6
- package/examples/js/shaders/VerticalTiltShiftShader.js +3 -6
- package/examples/js/shaders/VignetteShader.js +3 -6
- package/examples/js/shaders/VolumeShader.js +2 -6
- package/examples/js/shaders/WaterRefractionShader.js +2 -6
- package/examples/js/textures/FlakesTexture.js +0 -1
- package/examples/js/utils/BufferGeometryUtils.js +237 -171
- package/examples/js/utils/CameraUtils.js +5 -20
- package/examples/js/utils/GPUStatsPanel.js +3 -12
- package/examples/js/utils/GeometryCompressionUtils.js +19 -44
- package/examples/js/utils/GeometryUtils.js +15 -36
- package/examples/js/utils/LDrawUtils.js +8 -11
- package/examples/js/utils/PackedPhongMaterial.js +6 -4
- package/examples/js/utils/SceneUtils.js +109 -14
- package/examples/js/utils/ShadowMapViewer.js +17 -14
- package/examples/js/utils/SkeletonUtils.js +13 -27
- package/examples/js/utils/UVsDebug.js +20 -12
- package/examples/js/utils/WorkerPool.js +1 -11
- package/examples/jsm/animation/CCDIKSolver.js +27 -3
- package/examples/jsm/animation/MMDPhysics.js +28 -22
- package/examples/jsm/capabilities/WebGPU.js +3 -1
- package/examples/jsm/controls/ArcballControls.js +17 -2
- package/examples/jsm/controls/FirstPersonControls.js +20 -27
- package/examples/jsm/controls/FlyControls.js +16 -24
- package/examples/jsm/controls/OrbitControls.js +44 -9
- package/examples/jsm/controls/PointerLockControls.js +0 -7
- package/examples/jsm/controls/TrackballControls.js +14 -5
- package/examples/jsm/controls/TransformControls.js +18 -16
- package/examples/jsm/csm/CSM.js +1 -0
- package/examples/jsm/csm/CSMHelper.js +30 -0
- package/examples/jsm/effects/AnaglyphEffect.js +2 -2
- package/examples/jsm/effects/OutlineEffect.js +4 -25
- package/examples/jsm/effects/ParallaxBarrierEffect.js +2 -2
- package/examples/jsm/effects/PeppersGhostEffect.js +2 -2
- package/examples/jsm/effects/StereoEffect.js +2 -2
- package/examples/jsm/environments/RoomEnvironment.js +23 -0
- package/examples/jsm/exporters/ColladaExporter.js +4 -13
- package/examples/jsm/exporters/DRACOExporter.js +0 -13
- package/examples/jsm/exporters/GLTFExporter.js +29 -110
- package/examples/jsm/exporters/KTX2Exporter.js +29 -29
- package/examples/jsm/exporters/OBJExporter.js +0 -18
- package/examples/jsm/exporters/PLYExporter.js +14 -22
- package/examples/jsm/exporters/STLExporter.js +1 -9
- package/examples/jsm/exporters/USDZExporter.js +107 -4
- package/examples/jsm/geometries/ConvexGeometry.js +1 -1
- package/examples/jsm/geometries/ParametricGeometry.js +0 -6
- package/examples/jsm/helpers/OctreeHelper.js +22 -8
- package/examples/jsm/helpers/VertexNormalsHelper.js +7 -1
- package/examples/jsm/helpers/VertexTangentsHelper.js +7 -0
- package/examples/jsm/helpers/ViewHelper.js +24 -0
- package/examples/jsm/interactive/HTMLMesh.js +14 -15
- package/examples/jsm/interactive/InteractiveGroup.js +4 -2
- package/examples/jsm/interactive/SelectionHelper.js +5 -3
- package/examples/jsm/libs/flow.module.js +610 -160
- package/examples/jsm/libs/lottie_canvas.module.js +14844 -0
- package/examples/jsm/libs/meshopt_decoder.module.js +97 -32
- package/examples/jsm/libs/utif.module.js +1579 -0
- package/examples/jsm/libs/zstddec.module.js +1 -0
- package/examples/jsm/lines/LineSegments2.js +4 -0
- package/examples/jsm/loaders/3DMLoader.js +1 -2
- package/examples/jsm/loaders/ColladaLoader.js +29 -0
- package/examples/jsm/loaders/DRACOLoader.js +2 -28
- package/examples/jsm/loaders/EXRLoader.js +3 -13
- package/examples/jsm/loaders/FBXLoader.js +26 -3
- package/examples/jsm/loaders/FontLoader.js +3 -16
- package/examples/jsm/loaders/GLTFLoader.js +321 -464
- package/examples/jsm/loaders/HDRCubeTextureLoader.js +0 -13
- package/examples/jsm/loaders/KTX2Loader.js +254 -53
- package/examples/jsm/loaders/LDrawLoader.js +149 -87
- package/examples/jsm/loaders/LottieLoader.js +4 -2
- package/examples/jsm/loaders/MaterialXLoader.js +728 -0
- package/examples/jsm/loaders/OBJLoader.js +6 -14
- package/examples/jsm/loaders/PCDLoader.js +60 -14
- package/examples/jsm/loaders/PLYLoader.js +71 -19
- package/examples/jsm/loaders/RGBELoader.js +1 -1
- package/examples/jsm/loaders/SVGLoader.js +231 -17
- package/examples/jsm/loaders/TIFFLoader.js +36 -0
- package/examples/jsm/loaders/USDZLoader.js +633 -0
- package/examples/jsm/loaders/VRMLLoader.js +36 -26
- package/examples/jsm/loaders/VTKLoader.js +1 -1
- package/examples/jsm/loaders/lwo/LWO2Parser.js +6 -8
- package/examples/jsm/loaders/lwo/LWO3Parser.js +6 -8
- package/examples/jsm/materials/MeshGouraudMaterial.js +423 -0
- package/examples/jsm/math/ColorConverter.js +1 -49
- package/examples/jsm/math/ConvexHull.js +4 -4
- package/examples/jsm/math/Octree.js +1 -1
- package/examples/jsm/misc/GPUComputationRenderer.js +43 -0
- package/examples/jsm/misc/Volume.js +169 -171
- package/examples/jsm/misc/VolumeSlice.js +78 -80
- package/examples/jsm/modifiers/SimplifyModifier.js +1 -1
- package/examples/jsm/node-editor/NodeEditor.js +91 -12
- package/examples/jsm/node-editor/accessors/MatcapUVEditor.js +1 -1
- package/examples/jsm/node-editor/accessors/NormalEditor.js +1 -1
- package/examples/jsm/node-editor/accessors/PositionEditor.js +1 -1
- package/examples/jsm/node-editor/accessors/UVEditor.js +1 -1
- package/examples/jsm/node-editor/core/BaseNode.js +10 -3
- package/examples/jsm/node-editor/display/BlendEditor.js +1 -1
- package/examples/jsm/node-editor/display/NormalMapEditor.js +1 -1
- package/examples/jsm/node-editor/inputs/ColorEditor.js +1 -1
- package/examples/jsm/node-editor/inputs/FloatEditor.js +1 -1
- package/examples/jsm/node-editor/inputs/SliderEditor.js +1 -1
- package/examples/jsm/node-editor/inputs/TextureEditor.js +1 -1
- package/examples/jsm/node-editor/inputs/Vector2Editor.js +1 -1
- package/examples/jsm/node-editor/inputs/Vector3Editor.js +1 -1
- package/examples/jsm/node-editor/inputs/Vector4Editor.js +1 -1
- package/examples/jsm/node-editor/materials/BasicMaterialEditor.js +7 -10
- package/examples/jsm/node-editor/materials/PointsMaterialEditor.js +1 -1
- package/examples/jsm/node-editor/materials/StandardMaterialEditor.js +7 -10
- package/examples/jsm/node-editor/math/AngleEditor.js +4 -4
- package/examples/jsm/node-editor/math/DotEditor.js +1 -1
- package/examples/jsm/node-editor/math/InvertEditor.js +3 -3
- package/examples/jsm/node-editor/math/LimiterEditor.js +1 -1
- package/examples/jsm/node-editor/math/NormalizeEditor.js +1 -1
- package/examples/jsm/node-editor/math/OperatorEditor.js +1 -1
- package/examples/jsm/node-editor/math/PowerEditor.js +1 -1
- package/examples/jsm/node-editor/math/TrigonometryEditor.js +1 -1
- package/examples/jsm/node-editor/procedural/CheckerEditor.js +1 -1
- package/examples/jsm/node-editor/scene/MeshEditor.js +11 -8
- package/examples/jsm/node-editor/utils/JoinEditor.js +1 -1
- package/examples/jsm/node-editor/utils/OscillatorEditor.js +1 -1
- package/examples/jsm/node-editor/utils/PreviewEditor.js +7 -3
- package/examples/jsm/node-editor/utils/SplitEditor.js +1 -1
- package/examples/jsm/node-editor/utils/TimerEditor.js +1 -1
- package/examples/jsm/nodes/Nodes.js +70 -13
- package/examples/jsm/nodes/accessors/BitangentNode.js +62 -0
- package/examples/jsm/nodes/accessors/CubeTextureNode.js +9 -5
- package/examples/jsm/nodes/accessors/NormalNode.js +8 -8
- package/examples/jsm/nodes/accessors/Object3DNode.js +1 -1
- package/examples/jsm/nodes/accessors/PositionNode.js +11 -5
- package/examples/jsm/nodes/accessors/ReferenceNode.js +1 -1
- package/examples/jsm/nodes/accessors/ReflectVectorNode.js +31 -0
- package/examples/jsm/nodes/accessors/SkinningNode.js +8 -1
- package/examples/jsm/nodes/accessors/TangentNode.js +95 -0
- package/examples/jsm/nodes/core/AttributeNode.js +32 -9
- package/examples/jsm/nodes/core/CodeNode.js +3 -3
- package/examples/jsm/nodes/core/FunctionCallNode.js +20 -5
- package/examples/jsm/nodes/core/FunctionNode.js +2 -2
- package/examples/jsm/nodes/core/Node.js +15 -13
- package/examples/jsm/nodes/core/NodeBuilder.js +67 -18
- package/examples/jsm/nodes/core/NodeFrame.js +2 -2
- package/examples/jsm/nodes/core/NodeUtils.js +23 -1
- package/examples/jsm/nodes/core/NodeVarying.js +17 -0
- package/examples/jsm/nodes/core/VaryingNode.js +56 -0
- package/examples/jsm/nodes/core/constants.js +13 -13
- package/examples/jsm/nodes/display/BlendModeNode.js +85 -0
- package/examples/jsm/nodes/display/ColorAdjustmentNode.js +84 -0
- package/examples/jsm/nodes/display/NormalMapNode.js +19 -12
- package/examples/jsm/nodes/display/PosterizeNode.js +25 -0
- package/examples/jsm/nodes/display/ViewportNode.js +106 -0
- package/examples/jsm/nodes/functions/BSDF/BRDF_GGX.js +5 -5
- package/examples/jsm/nodes/functions/PhysicalLightingModel.js +3 -3
- package/examples/jsm/nodes/functions/light/getDistanceAttenuation.js +2 -2
- package/examples/jsm/nodes/geometry/RangeNode.js +109 -0
- package/examples/jsm/nodes/gpgpu/ComputeNode.js +3 -1
- package/examples/jsm/nodes/lighting/AnalyticLightNode.js +1 -1
- package/examples/jsm/nodes/lighting/EnvironmentNode.js +8 -7
- package/examples/jsm/nodes/lighting/LightingContextNode.js +4 -4
- package/examples/jsm/nodes/loaders/NodeLoader.js +2 -2
- package/examples/jsm/nodes/loaders/NodeMaterialLoader.js +33 -0
- package/examples/jsm/nodes/materials/Materials.js +21 -31
- package/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js +70 -0
- package/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +4 -7
- package/examples/jsm/nodes/materials/NodeMaterial.js +11 -3
- package/examples/jsm/nodes/materials/SpriteNodeMaterial.js +28 -17
- package/examples/jsm/nodes/materialx/DISCLAIMER.md +199 -0
- package/examples/jsm/nodes/materialx/MaterialXNodes.js +59 -0
- package/examples/jsm/nodes/materialx/lib/mx_hsv.js +56 -0
- package/examples/jsm/nodes/materialx/lib/mx_noise.js +617 -0
- package/examples/jsm/nodes/materialx/lib/mx_transform_color.js +18 -0
- package/examples/jsm/nodes/math/MathNode.js +7 -17
- package/examples/jsm/nodes/math/OperatorNode.js +16 -3
- package/examples/jsm/nodes/parsers/GLSLNodeFunction.js +21 -6
- package/examples/jsm/nodes/procedural/CheckerNode.js +2 -2
- package/examples/jsm/nodes/shadernode/ShaderNode.js +40 -25
- package/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js +95 -68
- package/examples/jsm/nodes/shadernode/ShaderNodeElements.js +49 -6
- package/examples/jsm/nodes/utils/ConvertNode.js +18 -12
- package/examples/jsm/nodes/utils/EquirectUVNode.js +27 -0
- package/examples/jsm/nodes/utils/JoinNode.js +15 -9
- package/examples/jsm/nodes/utils/MatcapUVNode.js +2 -4
- package/examples/jsm/nodes/utils/MaxMipLevelNode.js +3 -2
- package/examples/jsm/nodes/utils/OscNode.js +2 -2
- package/examples/jsm/nodes/utils/RemapNode.js +34 -0
- package/examples/jsm/nodes/utils/RotateUVNode.js +32 -0
- package/examples/jsm/nodes/utils/SplitNode.js +21 -5
- package/examples/jsm/nodes/utils/SpriteSheetUVNode.js +8 -10
- package/examples/jsm/nodes/utils/TimerNode.js +23 -3
- package/examples/jsm/nodes/utils/TriplanarTexturesNode.js +51 -0
- package/examples/jsm/objects/GroundProjectedEnv.js +186 -0
- package/examples/jsm/objects/Reflector.js +12 -5
- package/examples/jsm/objects/ReflectorForSSRPass.js +3 -5
- package/examples/jsm/objects/Refractor.js +12 -6
- package/examples/jsm/objects/ShadowMesh.js +8 -2
- package/examples/jsm/postprocessing/AfterimagePass.js +17 -4
- package/examples/jsm/postprocessing/BloomPass.js +22 -3
- package/examples/jsm/postprocessing/BokehPass.js +18 -4
- package/examples/jsm/postprocessing/CubeTexturePass.js +12 -5
- package/examples/jsm/postprocessing/DotScreenPass.js +8 -0
- package/examples/jsm/postprocessing/EffectComposer.js +9 -0
- package/examples/jsm/postprocessing/FilmPass.js +8 -0
- package/examples/jsm/postprocessing/GlitchPass.js +13 -1
- package/examples/jsm/postprocessing/HalftonePass.js +8 -0
- package/examples/jsm/postprocessing/OutlinePass.js +25 -3
- package/examples/jsm/postprocessing/Pass.js +2 -0
- package/examples/jsm/postprocessing/RenderPixelatedPass.js +234 -0
- package/examples/jsm/postprocessing/SAOPass.js +20 -0
- package/examples/jsm/postprocessing/SMAAPass.js +16 -0
- package/examples/jsm/postprocessing/SSAARenderPass.js +4 -0
- package/examples/jsm/postprocessing/SavePass.js +17 -1
- package/examples/jsm/postprocessing/ShaderPass.js +8 -0
- package/examples/jsm/postprocessing/TAARenderPass.js +9 -0
- package/examples/jsm/postprocessing/TexturePass.js +8 -0
- package/examples/jsm/postprocessing/UnrealBloomPass.js +16 -0
- package/examples/jsm/renderers/CSS2DRenderer.js +2 -2
- package/examples/jsm/renderers/CSS3DRenderer.js +2 -2
- package/examples/jsm/renderers/Projector.js +2 -24
- package/examples/jsm/renderers/webgl/nodes/SlotNode.js +9 -5
- package/examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js +363 -231
- package/examples/jsm/renderers/webgl/nodes/WebGLNodes.js +7 -3
- package/examples/jsm/renderers/webgpu/WebGPUAnimation.js +58 -0
- package/examples/jsm/renderers/webgpu/WebGPUAttributes.js +63 -5
- package/examples/jsm/renderers/webgpu/WebGPUBackground.js +68 -3
- package/examples/jsm/renderers/webgpu/WebGPUComputePipelines.js +6 -0
- package/examples/jsm/renderers/webgpu/WebGPUGeometries.js +6 -0
- package/examples/jsm/renderers/webgpu/WebGPUObjects.js +1 -1
- package/examples/jsm/renderers/webgpu/WebGPURenderPipeline.js +17 -19
- package/examples/jsm/renderers/webgpu/WebGPURenderPipelines.js +16 -14
- package/examples/jsm/renderers/webgpu/WebGPURenderStates.js +2 -2
- package/examples/jsm/renderers/webgpu/WebGPURenderer.js +113 -93
- package/examples/jsm/renderers/webgpu/WebGPUTextureUtils.js +5 -3
- package/examples/jsm/renderers/webgpu/WebGPUTextures.js +2 -2
- package/examples/jsm/renderers/webgpu/WebGPUUtils.js +81 -0
- package/examples/jsm/renderers/webgpu/nodes/WebGPUNodeBuilder.js +63 -36
- package/examples/jsm/renderers/webgpu/nodes/WebGPUNodes.js +1 -1
- package/examples/jsm/shaders/LuminosityShader.js +1 -1
- package/examples/jsm/shaders/MMDToonShader.js +2 -4
- package/examples/jsm/shaders/ToneMapShader.js +1 -1
- package/examples/jsm/shaders/VelocityShader.js +128 -0
- package/examples/jsm/utils/BufferGeometryUtils.js +176 -43
- package/examples/jsm/utils/GeometryUtils.js +17 -25
- package/examples/jsm/utils/PackedPhongMaterial.js +0 -1
- package/examples/jsm/utils/SceneUtils.js +117 -12
- package/examples/jsm/webxr/OculusHandModel.js +3 -2
- package/examples/jsm/webxr/OculusHandPointerModel.js +6 -1
- package/examples/jsm/webxr/VRButton.js +1 -7
- package/examples/jsm/webxr/XRHandMeshModel.js +8 -3
- package/package.json +22 -18
- package/src/Three.Legacy.js +262 -36
- package/src/Three.js +4 -2
- package/src/animation/AnimationAction.js +6 -5
- package/src/animation/AnimationClip.js +1 -1
- package/src/animation/AnimationMixer.js +1 -1
- package/src/animation/AnimationUtils.js +204 -199
- package/src/animation/KeyframeTrack.js +1 -1
- package/src/animation/PropertyBinding.js +31 -5
- package/src/audio/AudioContext.js +5 -5
- package/src/cameras/CubeCamera.js +14 -21
- package/src/constants.js +2 -4
- package/src/core/BufferAttribute.js +81 -111
- package/src/core/BufferGeometry.js +3 -41
- package/src/core/InstancedBufferAttribute.js +0 -10
- package/src/core/InstancedBufferGeometry.js +1 -7
- package/src/core/InterleavedBuffer.js +1 -1
- package/src/core/InterleavedBufferAttribute.js +57 -8
- package/src/core/Object3D.js +22 -5
- package/src/core/Uniform.js +0 -7
- package/src/core/UniformsGroup.js +92 -0
- package/src/extras/DataUtils.js +104 -88
- package/src/extras/Earcut.js +67 -67
- package/src/extras/core/Path.js +1 -0
- package/src/extras/core/ShapePath.js +1 -4
- package/src/extras/curves/CatmullRomCurve3.js +4 -2
- package/src/geometries/BoxGeometry.js +1 -1
- package/src/geometries/CapsuleGeometry.js +1 -1
- package/src/geometries/CircleGeometry.js +1 -1
- package/src/geometries/ConeGeometry.js +1 -1
- package/src/geometries/CylinderGeometry.js +2 -1
- package/src/geometries/DodecahedronGeometry.js +1 -1
- package/src/geometries/EdgesGeometry.js +5 -4
- package/src/geometries/ExtrudeGeometry.js +2 -11
- package/src/geometries/IcosahedronGeometry.js +1 -1
- package/src/geometries/LatheGeometry.js +2 -2
- package/src/geometries/OctahedronGeometry.js +1 -1
- package/src/geometries/PlaneGeometry.js +2 -1
- package/src/geometries/PolyhedronGeometry.js +2 -2
- package/src/geometries/RingGeometry.js +1 -1
- package/src/geometries/ShapeGeometry.js +3 -2
- package/src/geometries/SphereGeometry.js +2 -1
- package/src/geometries/TetrahedronGeometry.js +1 -1
- package/src/geometries/TorusGeometry.js +2 -1
- package/src/geometries/TorusKnotGeometry.js +2 -1
- package/src/geometries/TubeGeometry.js +2 -1
- package/src/geometries/WireframeGeometry.js +1 -0
- package/src/helpers/ArrowHelper.js +9 -0
- package/src/helpers/Box3Helper.js +7 -0
- package/src/helpers/BoxHelper.js +7 -1
- package/src/helpers/CameraHelper.js +97 -38
- package/src/helpers/DirectionalLightHelper.js +6 -1
- package/src/helpers/GridHelper.js +7 -0
- package/src/helpers/HemisphereLightHelper.js +5 -1
- package/src/helpers/PlaneHelper.js +15 -9
- package/src/helpers/PointLightHelper.js +2 -1
- package/src/helpers/PolarGridHelper.js +25 -14
- package/src/helpers/SkeletonHelper.js +7 -0
- package/src/helpers/SpotLightHelper.js +5 -2
- package/src/lights/LightShadow.js +1 -2
- package/src/lights/PointLight.js +2 -2
- package/src/lights/SpotLight.js +4 -2
- package/src/loaders/FileLoader.js +16 -2
- package/src/loaders/LoadingManager.js +1 -1
- package/src/loaders/MaterialLoader.js +49 -7
- package/src/loaders/ObjectLoader.js +9 -42
- package/src/materials/Material.js +2 -34
- package/src/materials/Materials.js +0 -27
- package/src/materials/MeshLambertMaterial.js +28 -1
- package/src/materials/MeshPhysicalMaterial.js +1 -1
- package/src/materials/ShaderMaterial.js +3 -7
- package/src/math/Color.js +8 -18
- package/src/math/MathUtils.js +1 -7
- package/src/math/Matrix3.js +54 -25
- package/src/math/Matrix4.js +3 -27
- package/src/math/Quaternion.js +1 -21
- package/src/math/Ray.js +2 -5
- package/src/math/Sphere.js +36 -21
- package/src/math/Vector2.js +4 -24
- package/src/math/Vector3.js +7 -46
- package/src/math/Vector4.js +4 -24
- package/src/objects/InstancedMesh.js +7 -0
- package/src/objects/LOD.js +25 -6
- package/src/renderers/WebGL3DRenderTarget.js +1 -1
- package/src/renderers/WebGLArrayRenderTarget.js +1 -1
- package/src/renderers/WebGLCubeRenderTarget.js +1 -1
- package/src/renderers/WebGLMultipleRenderTargets.js +1 -1
- package/src/renderers/WebGLRenderTarget.js +1 -1
- package/src/renderers/WebGLRenderer.js +119 -69
- package/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js +12 -12
- package/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js +3 -5
- package/src/renderers/shaders/ShaderChunk/common.glsl.js +6 -5
- package/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js +24 -24
- package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +0 -4
- package/src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/gradientmap_pars_fragment.glsl.js +2 -1
- package/src/renderers/shaders/ShaderChunk/iridescence_fragment.glsl.js +113 -99
- package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +34 -13
- package/src/renderers/shaders/ShaderChunk/lights_lambert_fragment.glsl.js +5 -0
- package/src/renderers/shaders/ShaderChunk/lights_lambert_pars_fragment.glsl.js +28 -0
- package/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl.js +0 -2
- package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +3 -1
- package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +13 -1
- package/src/renderers/shaders/ShaderChunk/lights_toon_pars_fragment.glsl.js +0 -2
- package/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js +2 -4
- package/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js +2 -4
- package/src/renderers/shaders/ShaderChunk/output_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/packing.glsl.js +8 -0
- package/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js +18 -7
- package/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js +8 -3
- package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +9 -6
- package/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +14 -10
- package/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +2 -2
- package/src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk.js +7 -2
- package/src/renderers/shaders/ShaderLib/background.glsl.js +7 -2
- package/src/renderers/shaders/ShaderLib/backgroundCube.glsl.js +62 -0
- package/src/renderers/shaders/ShaderLib/cube.glsl.js +4 -6
- package/src/renderers/shaders/ShaderLib/meshbasic.glsl.js +0 -1
- package/src/renderers/shaders/ShaderLib/meshlambert.glsl.js +22 -50
- package/src/renderers/shaders/ShaderLib/meshphong.glsl.js +0 -1
- package/src/renderers/shaders/ShaderLib/vsm.glsl.js +0 -3
- package/src/renderers/shaders/ShaderLib.js +50 -36
- package/src/renderers/shaders/UniformsLib.js +13 -12
- package/src/renderers/shaders/UniformsUtils.js +29 -0
- package/src/renderers/webgl/WebGLAttributes.js +2 -0
- package/src/renderers/webgl/WebGLBackground.js +17 -9
- package/src/renderers/webgl/WebGLLights.js +37 -17
- package/src/renderers/webgl/WebGLMaterials.js +2 -1
- package/src/renderers/webgl/WebGLMorphtargets.js +0 -20
- package/src/renderers/webgl/WebGLProgram.js +6 -11
- package/src/renderers/webgl/WebGLPrograms.js +30 -26
- package/src/renderers/webgl/WebGLRenderLists.js +5 -4
- package/src/renderers/webgl/WebGLRenderStates.js +5 -4
- package/src/renderers/webgl/WebGLShaderCache.js +9 -6
- package/src/renderers/webgl/WebGLShadowMap.js +13 -16
- package/src/renderers/webgl/WebGLState.js +125 -41
- package/src/renderers/webgl/WebGLTextures.js +94 -39
- package/src/renderers/webgl/WebGLUniforms.js +156 -28
- package/src/renderers/webgl/WebGLUniformsGroups.js +372 -0
- package/src/renderers/webgl/WebGLUtils.js +3 -1
- package/src/renderers/webvr/WebVRManager.js +42 -9
- package/src/renderers/webvr/WebVRUtils.js +1 -1
- package/src/renderers/webxr/WebXRController.js +91 -50
- package/src/renderers/webxr/WebXRManager.js +127 -34
- package/src/scenes/Scene.js +24 -3
- package/src/textures/CompressedArrayTexture.js +18 -0
- package/src/textures/Source.js +1 -1
- package/src/textures/Texture.js +2 -1
- package/src/utils.js +1 -1
- package/examples/js/controls/experimental/CameraControls.js +0 -1048
- package/examples/js/libs/lottie_canvas.js +0 -12751
- package/examples/js/loaders/KTX2Loader.js +0 -558
- package/examples/js/shaders/PixelShader.js +0 -51
- package/examples/jsm/controls/experimental/CameraControls.js +0 -1248
- package/examples/jsm/nodes/accessors/ReflectNode.js +0 -70
- package/examples/jsm/nodes/core/NodeVary.js +0 -14
- package/examples/jsm/nodes/core/VaryNode.js +0 -54
- package/examples/jsm/package.json +0 -3
- package/examples/jsm/renderers/webgl/nodes/WebGLPhysicalContextNode.js +0 -45
- package/examples/jsm/shaders/PixelShader.js +0 -44
- package/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl.js +0 -122
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
( function () {
|
|
2
2
|
|
|
3
|
+
// Special surface finish tag types.
|
|
3
4
|
// Note: "MATERIAL" tag (e.g. GLITTER, SPECKLE) is not implemented
|
|
4
|
-
|
|
5
5
|
const FINISH_TYPE_DEFAULT = 0;
|
|
6
6
|
const FINISH_TYPE_CHROME = 1;
|
|
7
7
|
const FINISH_TYPE_PEARLESCENT = 2;
|
|
8
8
|
const FINISH_TYPE_RUBBER = 3;
|
|
9
9
|
const FINISH_TYPE_MATTE_METALLIC = 4;
|
|
10
|
-
const FINISH_TYPE_METAL = 5;
|
|
11
|
-
// The LDraw standard establishes these various possible subfolders.
|
|
10
|
+
const FINISH_TYPE_METAL = 5;
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
12
|
+
// State machine to search a subobject path.
|
|
13
|
+
// The LDraw standard establishes these various possible subfolders.
|
|
14
|
+
const FILE_LOCATION_TRY_PARTS = 0;
|
|
15
|
+
const FILE_LOCATION_TRY_P = 1;
|
|
16
|
+
const FILE_LOCATION_TRY_MODELS = 2;
|
|
17
|
+
const FILE_LOCATION_AS_IS = 3;
|
|
17
18
|
const FILE_LOCATION_TRY_RELATIVE = 4;
|
|
18
19
|
const FILE_LOCATION_TRY_ABSOLUTE = 5;
|
|
19
20
|
const FILE_LOCATION_NOT_FOUND = 6;
|
|
20
21
|
const MAIN_COLOUR_CODE = '16';
|
|
21
22
|
const MAIN_EDGE_COLOUR_CODE = '24';
|
|
22
|
-
|
|
23
23
|
const _tempVec0 = new THREE.Vector3();
|
|
24
|
-
|
|
25
24
|
const _tempVec1 = new THREE.Vector3();
|
|
26
|
-
|
|
27
25
|
class LDrawConditionalLineMaterial extends THREE.ShaderMaterial {
|
|
28
26
|
|
|
29
27
|
constructor( parameters ) {
|
|
@@ -37,9 +35,7 @@
|
|
|
37
35
|
value: 1.0
|
|
38
36
|
}
|
|
39
37
|
} ] ),
|
|
40
|
-
vertexShader:
|
|
41
|
-
/* glsl */
|
|
42
|
-
`
|
|
38
|
+
vertexShader: /* glsl */`
|
|
43
39
|
attribute vec3 control0;
|
|
44
40
|
attribute vec3 control1;
|
|
45
41
|
attribute vec3 direction;
|
|
@@ -86,9 +82,7 @@
|
|
|
86
82
|
#include <fog_vertex>
|
|
87
83
|
}
|
|
88
84
|
`,
|
|
89
|
-
fragmentShader:
|
|
90
|
-
/* glsl */
|
|
91
|
-
`
|
|
85
|
+
fragmentShader: /* glsl */`
|
|
92
86
|
uniform vec3 diffuse;
|
|
93
87
|
uniform float opacity;
|
|
94
88
|
varying float discardFlag;
|
|
@@ -143,7 +137,6 @@
|
|
|
143
137
|
}
|
|
144
138
|
|
|
145
139
|
}
|
|
146
|
-
|
|
147
140
|
class ConditionalLineSegments extends THREE.LineSegments {
|
|
148
141
|
|
|
149
142
|
constructor( geometry, material ) {
|
|
@@ -154,7 +147,6 @@
|
|
|
154
147
|
}
|
|
155
148
|
|
|
156
149
|
}
|
|
157
|
-
|
|
158
150
|
function generateFaceNormals( faces ) {
|
|
159
151
|
|
|
160
152
|
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
@@ -164,11 +156,8 @@
|
|
|
164
156
|
const v0 = vertices[ 0 ];
|
|
165
157
|
const v1 = vertices[ 1 ];
|
|
166
158
|
const v2 = vertices[ 2 ];
|
|
167
|
-
|
|
168
159
|
_tempVec0.subVectors( v1, v0 );
|
|
169
|
-
|
|
170
160
|
_tempVec1.subVectors( v2, v1 );
|
|
171
|
-
|
|
172
161
|
face.faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize();
|
|
173
162
|
|
|
174
163
|
}
|
|
@@ -176,7 +165,6 @@
|
|
|
176
165
|
}
|
|
177
166
|
|
|
178
167
|
const _ray = new THREE.Ray();
|
|
179
|
-
|
|
180
168
|
function smoothNormals( faces, lineSegments, checkSubSegments = false ) {
|
|
181
169
|
|
|
182
170
|
// NOTE: 1e2 is pretty coarse but was chosen to quantize the resulting value because
|
|
@@ -187,8 +175,8 @@
|
|
|
187
175
|
// vertices that should be merged might be set to "1.7" and "1.6999..." meaning they won't
|
|
188
176
|
// get merged. This added epsilon attempts to push these error values to the same quantized
|
|
189
177
|
// value for the sake of hashing. See "AT-ST mini" dishes. See mrdoob/three#23169.
|
|
190
|
-
const hashMultiplier = ( 1 + 1e-10 ) * 1e2;
|
|
191
178
|
|
|
179
|
+
const hashMultiplier = ( 1 + 1e-10 ) * 1e2;
|
|
192
180
|
function hashVertex( v ) {
|
|
193
181
|
|
|
194
182
|
const x = ~ ~ ( v.x * hashMultiplier );
|
|
@@ -202,10 +190,10 @@
|
|
|
202
190
|
|
|
203
191
|
return `${hashVertex( v0 )}_${hashVertex( v1 )}`;
|
|
204
192
|
|
|
205
|
-
}
|
|
206
|
-
// onto the original line.
|
|
207
|
-
|
|
193
|
+
}
|
|
208
194
|
|
|
195
|
+
// converts the two vertices to a ray with a normalized direction and origin of 0, 0, 0 projected
|
|
196
|
+
// onto the original line.
|
|
209
197
|
function toNormalizedRay( v0, v1, targetRay ) {
|
|
210
198
|
|
|
211
199
|
targetRay.direction.subVectors( v1, v0 ).normalize();
|
|
@@ -224,8 +212,9 @@
|
|
|
224
212
|
const hardEdges = new Set();
|
|
225
213
|
const hardEdgeRays = new Map();
|
|
226
214
|
const halfEdgeList = {};
|
|
227
|
-
const normals = [];
|
|
215
|
+
const normals = [];
|
|
228
216
|
|
|
217
|
+
// Save the list of hard edges by hash
|
|
229
218
|
for ( let i = 0, l = lineSegments.length; i < l; i ++ ) {
|
|
230
219
|
|
|
231
220
|
const ls = lineSegments[ i ];
|
|
@@ -233,15 +222,15 @@
|
|
|
233
222
|
const v0 = vertices[ 0 ];
|
|
234
223
|
const v1 = vertices[ 1 ];
|
|
235
224
|
hardEdges.add( hashEdge( v0, v1 ) );
|
|
236
|
-
hardEdges.add( hashEdge( v1, v0 ) );
|
|
237
|
-
// and requires more memory.
|
|
225
|
+
hardEdges.add( hashEdge( v1, v0 ) );
|
|
238
226
|
|
|
227
|
+
// only generate the hard edge ray map if we're checking subsegments because it's more expensive to check
|
|
228
|
+
// and requires more memory.
|
|
239
229
|
if ( checkSubSegments ) {
|
|
240
230
|
|
|
241
231
|
// add both ray directions to the map
|
|
242
232
|
const ray = toNormalizedRay( v0, v1, new THREE.Ray() );
|
|
243
233
|
const rh1 = hashRay( ray );
|
|
244
|
-
|
|
245
234
|
if ( ! hardEdgeRays.has( rh1 ) ) {
|
|
246
235
|
|
|
247
236
|
toNormalizedRay( v1, v0, ray );
|
|
@@ -253,14 +242,13 @@
|
|
|
253
242
|
hardEdgeRays.set( rh1, info );
|
|
254
243
|
hardEdgeRays.set( rh2, info );
|
|
255
244
|
|
|
256
|
-
}
|
|
257
|
-
// subsegment later.
|
|
258
|
-
|
|
245
|
+
}
|
|
259
246
|
|
|
247
|
+
// store both segments ends in min, max order in the distances array to check if a face edge is a
|
|
248
|
+
// subsegment later.
|
|
260
249
|
const info = hardEdgeRays.get( rh1 );
|
|
261
250
|
let d0 = info.ray.direction.dot( v0 );
|
|
262
251
|
let d1 = info.ray.direction.dot( v1 );
|
|
263
|
-
|
|
264
252
|
if ( d0 > d1 ) {
|
|
265
253
|
|
|
266
254
|
[ d0, d1 ] = [ d1, d0 ];
|
|
@@ -271,35 +259,34 @@
|
|
|
271
259
|
|
|
272
260
|
}
|
|
273
261
|
|
|
274
|
-
}
|
|
275
|
-
|
|
262
|
+
}
|
|
276
263
|
|
|
264
|
+
// track the half edges associated with each triangle
|
|
277
265
|
for ( let i = 0, l = faces.length; i < l; i ++ ) {
|
|
278
266
|
|
|
279
267
|
const tri = faces[ i ];
|
|
280
268
|
const vertices = tri.vertices;
|
|
281
269
|
const vertCount = vertices.length;
|
|
282
|
-
|
|
283
270
|
for ( let i2 = 0; i2 < vertCount; i2 ++ ) {
|
|
284
271
|
|
|
285
272
|
const index = i2;
|
|
286
273
|
const next = ( i2 + 1 ) % vertCount;
|
|
287
274
|
const v0 = vertices[ index ];
|
|
288
275
|
const v1 = vertices[ next ];
|
|
289
|
-
const hash = hashEdge( v0, v1 );
|
|
276
|
+
const hash = hashEdge( v0, v1 );
|
|
290
277
|
|
|
278
|
+
// don't add the triangle if the edge is supposed to be hard
|
|
291
279
|
if ( hardEdges.has( hash ) ) {
|
|
292
280
|
|
|
293
281
|
continue;
|
|
294
282
|
|
|
295
|
-
}
|
|
296
|
-
|
|
283
|
+
}
|
|
297
284
|
|
|
285
|
+
// if checking subsegments then check to see if this edge lies on a hard edge ray and whether its within any ray bounds
|
|
298
286
|
if ( checkSubSegments ) {
|
|
299
287
|
|
|
300
288
|
toNormalizedRay( v0, v1, _ray );
|
|
301
289
|
const rayHash = hashRay( _ray );
|
|
302
|
-
|
|
303
290
|
if ( hardEdgeRays.has( rayHash ) ) {
|
|
304
291
|
|
|
305
292
|
const info = hardEdgeRays.get( rayHash );
|
|
@@ -309,16 +296,14 @@
|
|
|
309
296
|
} = info;
|
|
310
297
|
let d0 = ray.direction.dot( v0 );
|
|
311
298
|
let d1 = ray.direction.dot( v1 );
|
|
312
|
-
|
|
313
299
|
if ( d0 > d1 ) {
|
|
314
300
|
|
|
315
301
|
[ d0, d1 ] = [ d1, d0 ];
|
|
316
302
|
|
|
317
|
-
}
|
|
318
|
-
|
|
303
|
+
}
|
|
319
304
|
|
|
305
|
+
// return early if the face edge is found to be a subsegment of a line edge meaning the edge will have "hard" normals
|
|
320
306
|
let found = false;
|
|
321
|
-
|
|
322
307
|
for ( let i = 0, l = distances.length; i < l; i += 2 ) {
|
|
323
308
|
|
|
324
309
|
if ( d0 >= distances[ i ] && d1 <= distances[ i + 1 ] ) {
|
|
@@ -348,14 +333,13 @@
|
|
|
348
333
|
|
|
349
334
|
}
|
|
350
335
|
|
|
351
|
-
}
|
|
352
|
-
|
|
336
|
+
}
|
|
353
337
|
|
|
338
|
+
// Iterate until we've tried to connect all faces to share normals
|
|
354
339
|
while ( true ) {
|
|
355
340
|
|
|
356
341
|
// Stop if there are no more faces left
|
|
357
342
|
let halfEdge = null;
|
|
358
|
-
|
|
359
343
|
for ( const key in halfEdgeList ) {
|
|
360
344
|
|
|
361
345
|
halfEdge = halfEdgeList[ key ];
|
|
@@ -367,62 +351,61 @@
|
|
|
367
351
|
|
|
368
352
|
break;
|
|
369
353
|
|
|
370
|
-
}
|
|
371
|
-
|
|
354
|
+
}
|
|
372
355
|
|
|
356
|
+
// Exhaustively find all connected faces
|
|
373
357
|
const queue = [ halfEdge ];
|
|
374
|
-
|
|
375
358
|
while ( queue.length > 0 ) {
|
|
376
359
|
|
|
377
360
|
// initialize all vertex normals in this triangle
|
|
378
361
|
const tri = queue.pop().tri;
|
|
379
362
|
const vertices = tri.vertices;
|
|
380
363
|
const vertNormals = tri.normals;
|
|
381
|
-
const faceNormal = tri.faceNormal;
|
|
364
|
+
const faceNormal = tri.faceNormal;
|
|
382
365
|
|
|
366
|
+
// Check if any edge is connected to another triangle edge
|
|
383
367
|
const vertCount = vertices.length;
|
|
384
|
-
|
|
385
368
|
for ( let i2 = 0; i2 < vertCount; i2 ++ ) {
|
|
386
369
|
|
|
387
370
|
const index = i2;
|
|
388
371
|
const next = ( i2 + 1 ) % vertCount;
|
|
389
372
|
const v0 = vertices[ index ];
|
|
390
|
-
const v1 = vertices[ next ];
|
|
373
|
+
const v1 = vertices[ next ];
|
|
391
374
|
|
|
375
|
+
// delete this triangle from the list so it won't be found again
|
|
392
376
|
const hash = hashEdge( v0, v1 );
|
|
393
377
|
delete halfEdgeList[ hash ];
|
|
394
378
|
const reverseHash = hashEdge( v1, v0 );
|
|
395
379
|
const otherInfo = halfEdgeList[ reverseHash ];
|
|
396
|
-
|
|
397
380
|
if ( otherInfo ) {
|
|
398
381
|
|
|
399
382
|
const otherTri = otherInfo.tri;
|
|
400
383
|
const otherIndex = otherInfo.index;
|
|
401
384
|
const otherNormals = otherTri.normals;
|
|
402
385
|
const otherVertCount = otherNormals.length;
|
|
403
|
-
const otherFaceNormal = otherTri.faceNormal;
|
|
386
|
+
const otherFaceNormal = otherTri.faceNormal;
|
|
387
|
+
|
|
388
|
+
// NOTE: If the angle between faces is > 67.5 degrees then assume it's
|
|
404
389
|
// hard edge. There are some cases where the line segments do not line up exactly
|
|
405
390
|
// with or span multiple triangle edges (see Lunar Vehicle wheels).
|
|
406
|
-
|
|
407
391
|
if ( Math.abs( otherTri.faceNormal.dot( tri.faceNormal ) ) < 0.25 ) {
|
|
408
392
|
|
|
409
393
|
continue;
|
|
410
394
|
|
|
411
|
-
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// if this triangle has already been traversed then it won't be in
|
|
412
398
|
// the halfEdgeList. If it has not then add it to the queue and delete
|
|
413
399
|
// it so it won't be found again.
|
|
414
|
-
|
|
415
|
-
|
|
416
400
|
if ( reverseHash in halfEdgeList ) {
|
|
417
401
|
|
|
418
402
|
queue.push( otherInfo );
|
|
419
403
|
delete halfEdgeList[ reverseHash ];
|
|
420
404
|
|
|
421
|
-
}
|
|
422
|
-
|
|
405
|
+
}
|
|
423
406
|
|
|
407
|
+
// share the first normal
|
|
424
408
|
const otherNext = ( otherIndex + 1 ) % otherVertCount;
|
|
425
|
-
|
|
426
409
|
if ( vertNormals[ index ] && otherNormals[ otherNext ] && vertNormals[ index ] !== otherNormals[ otherNext ] ) {
|
|
427
410
|
|
|
428
411
|
otherNormals[ otherNext ].norm.add( vertNormals[ index ].norm );
|
|
@@ -431,7 +414,6 @@
|
|
|
431
414
|
}
|
|
432
415
|
|
|
433
416
|
let sharedNormal1 = vertNormals[ index ] || otherNormals[ otherNext ];
|
|
434
|
-
|
|
435
417
|
if ( sharedNormal1 === null ) {
|
|
436
418
|
|
|
437
419
|
// it's possible to encounter an edge of a triangle that has already been traversed meaning
|
|
@@ -456,9 +438,9 @@
|
|
|
456
438
|
otherNormals[ otherNext ] = sharedNormal1;
|
|
457
439
|
sharedNormal1.norm.add( otherFaceNormal );
|
|
458
440
|
|
|
459
|
-
}
|
|
460
|
-
|
|
441
|
+
}
|
|
461
442
|
|
|
443
|
+
// share the second normal
|
|
462
444
|
if ( vertNormals[ next ] && otherNormals[ otherIndex ] && vertNormals[ next ] !== otherNormals[ otherIndex ] ) {
|
|
463
445
|
|
|
464
446
|
otherNormals[ otherIndex ].norm.add( vertNormals[ next ].norm );
|
|
@@ -467,7 +449,6 @@
|
|
|
467
449
|
}
|
|
468
450
|
|
|
469
451
|
let sharedNormal2 = vertNormals[ next ] || otherNormals[ otherIndex ];
|
|
470
|
-
|
|
471
452
|
if ( sharedNormal2 === null ) {
|
|
472
453
|
|
|
473
454
|
sharedNormal2 = {
|
|
@@ -497,9 +478,9 @@
|
|
|
497
478
|
|
|
498
479
|
}
|
|
499
480
|
|
|
500
|
-
}
|
|
501
|
-
|
|
481
|
+
}
|
|
502
482
|
|
|
483
|
+
// The normals of each face have been added up so now we average them by normalizing the vector.
|
|
503
484
|
for ( let i = 0, l = normals.length; i < l; i ++ ) {
|
|
504
485
|
|
|
505
486
|
normals[ i ].normalize();
|
|
@@ -531,13 +512,11 @@
|
|
|
531
512
|
this.lineNumber = lineNumber;
|
|
532
513
|
|
|
533
514
|
}
|
|
534
|
-
|
|
535
515
|
seekNonSpace() {
|
|
536
516
|
|
|
537
517
|
while ( this.currentCharIndex < this.lineLength ) {
|
|
538
518
|
|
|
539
519
|
this.currentChar = this.line.charAt( this.currentCharIndex );
|
|
540
|
-
|
|
541
520
|
if ( this.currentChar !== ' ' && this.currentChar !== '\t' ) {
|
|
542
521
|
|
|
543
522
|
return;
|
|
@@ -549,15 +528,14 @@
|
|
|
549
528
|
}
|
|
550
529
|
|
|
551
530
|
}
|
|
552
|
-
|
|
553
531
|
getToken() {
|
|
554
532
|
|
|
555
|
-
const pos0 = this.currentCharIndex ++;
|
|
533
|
+
const pos0 = this.currentCharIndex ++;
|
|
556
534
|
|
|
535
|
+
// Seek space
|
|
557
536
|
while ( this.currentCharIndex < this.lineLength ) {
|
|
558
537
|
|
|
559
538
|
this.currentChar = this.line.charAt( this.currentCharIndex );
|
|
560
|
-
|
|
561
539
|
if ( this.currentChar === ' ' || this.currentChar === '\t' ) {
|
|
562
540
|
|
|
563
541
|
break;
|
|
@@ -573,40 +551,35 @@
|
|
|
573
551
|
return this.line.substring( pos0, pos1 );
|
|
574
552
|
|
|
575
553
|
}
|
|
576
|
-
|
|
577
554
|
getVector() {
|
|
578
555
|
|
|
579
556
|
return new THREE.Vector3( parseFloat( this.getToken() ), parseFloat( this.getToken() ), parseFloat( this.getToken() ) );
|
|
580
557
|
|
|
581
558
|
}
|
|
582
|
-
|
|
583
559
|
getRemainingString() {
|
|
584
560
|
|
|
585
561
|
return this.line.substring( this.currentCharIndex, this.lineLength );
|
|
586
562
|
|
|
587
563
|
}
|
|
588
|
-
|
|
589
564
|
isAtTheEnd() {
|
|
590
565
|
|
|
591
566
|
return this.currentCharIndex >= this.lineLength;
|
|
592
567
|
|
|
593
568
|
}
|
|
594
|
-
|
|
595
569
|
setToEnd() {
|
|
596
570
|
|
|
597
571
|
this.currentCharIndex = this.lineLength;
|
|
598
572
|
|
|
599
573
|
}
|
|
600
|
-
|
|
601
574
|
getLineNumberString() {
|
|
602
575
|
|
|
603
576
|
return this.lineNumber >= 0 ? ' at line ' + this.lineNumber : '';
|
|
604
577
|
|
|
605
578
|
}
|
|
606
579
|
|
|
607
|
-
}
|
|
608
|
-
|
|
580
|
+
}
|
|
609
581
|
|
|
582
|
+
// Fetches and parses an intermediate representation of LDraw parts files.
|
|
610
583
|
class LDrawParsedCache {
|
|
611
584
|
|
|
612
585
|
constructor( loader ) {
|
|
@@ -615,12 +588,12 @@
|
|
|
615
588
|
this._cache = {};
|
|
616
589
|
|
|
617
590
|
}
|
|
618
|
-
|
|
619
591
|
cloneResult( original ) {
|
|
620
592
|
|
|
621
|
-
const result = {};
|
|
622
|
-
// so these pieces must be cloned.
|
|
593
|
+
const result = {};
|
|
623
594
|
|
|
595
|
+
// vertices are transformed and normals computed before being converted to geometry
|
|
596
|
+
// so these pieces must be cloned.
|
|
624
597
|
result.faces = original.faces.map( face => {
|
|
625
598
|
|
|
626
599
|
return {
|
|
@@ -650,55 +623,50 @@
|
|
|
650
623
|
vertices: face.vertices.map( v => v.clone() )
|
|
651
624
|
};
|
|
652
625
|
|
|
653
|
-
} );
|
|
626
|
+
} );
|
|
654
627
|
|
|
628
|
+
// none if this is subsequently modified
|
|
655
629
|
result.type = original.type;
|
|
656
630
|
result.category = original.category;
|
|
657
631
|
result.keywords = original.keywords;
|
|
632
|
+
result.author = original.author;
|
|
658
633
|
result.subobjects = original.subobjects;
|
|
634
|
+
result.fileName = original.fileName;
|
|
659
635
|
result.totalFaces = original.totalFaces;
|
|
660
|
-
result.
|
|
636
|
+
result.startingBuildingStep = original.startingBuildingStep;
|
|
661
637
|
result.materials = original.materials;
|
|
662
638
|
result.group = null;
|
|
663
639
|
return result;
|
|
664
640
|
|
|
665
641
|
}
|
|
666
|
-
|
|
667
642
|
async fetchData( fileName ) {
|
|
668
643
|
|
|
669
644
|
let triedLowerCase = false;
|
|
670
|
-
let locationState =
|
|
671
|
-
|
|
645
|
+
let locationState = FILE_LOCATION_TRY_PARTS;
|
|
672
646
|
while ( locationState !== FILE_LOCATION_NOT_FOUND ) {
|
|
673
647
|
|
|
674
648
|
let subobjectURL = fileName;
|
|
675
|
-
|
|
676
649
|
switch ( locationState ) {
|
|
677
650
|
|
|
678
651
|
case FILE_LOCATION_AS_IS:
|
|
679
652
|
locationState = locationState + 1;
|
|
680
653
|
break;
|
|
681
|
-
|
|
682
654
|
case FILE_LOCATION_TRY_PARTS:
|
|
683
655
|
subobjectURL = 'parts/' + subobjectURL;
|
|
684
656
|
locationState = locationState + 1;
|
|
685
657
|
break;
|
|
686
|
-
|
|
687
658
|
case FILE_LOCATION_TRY_P:
|
|
688
659
|
subobjectURL = 'p/' + subobjectURL;
|
|
689
660
|
locationState = locationState + 1;
|
|
690
661
|
break;
|
|
691
|
-
|
|
692
662
|
case FILE_LOCATION_TRY_MODELS:
|
|
693
663
|
subobjectURL = 'models/' + subobjectURL;
|
|
694
664
|
locationState = locationState + 1;
|
|
695
665
|
break;
|
|
696
|
-
|
|
697
666
|
case FILE_LOCATION_TRY_RELATIVE:
|
|
698
667
|
subobjectURL = fileName.substring( 0, fileName.lastIndexOf( '/' ) + 1 ) + subobjectURL;
|
|
699
668
|
locationState = locationState + 1;
|
|
700
669
|
break;
|
|
701
|
-
|
|
702
670
|
case FILE_LOCATION_TRY_ABSOLUTE:
|
|
703
671
|
if ( triedLowerCase ) {
|
|
704
672
|
|
|
@@ -711,7 +679,7 @@
|
|
|
711
679
|
fileName = fileName.toLowerCase();
|
|
712
680
|
subobjectURL = fileName;
|
|
713
681
|
triedLowerCase = true;
|
|
714
|
-
locationState =
|
|
682
|
+
locationState = FILE_LOCATION_TRY_PARTS;
|
|
715
683
|
|
|
716
684
|
}
|
|
717
685
|
|
|
@@ -724,7 +692,6 @@
|
|
|
724
692
|
fileLoader.setPath( loader.partsLibraryPath );
|
|
725
693
|
fileLoader.setRequestHeader( loader.requestHeader );
|
|
726
694
|
fileLoader.setWithCredentials( loader.withCredentials );
|
|
727
|
-
|
|
728
695
|
try {
|
|
729
696
|
|
|
730
697
|
const text = await fileLoader.loadAsync( subobjectURL );
|
|
@@ -741,17 +708,16 @@
|
|
|
741
708
|
throw new Error( 'LDrawLoader: Subobject "' + fileName + '" could not be loaded.' );
|
|
742
709
|
|
|
743
710
|
}
|
|
744
|
-
|
|
745
711
|
parse( text, fileName = null ) {
|
|
746
712
|
|
|
747
|
-
const loader = this.loader;
|
|
713
|
+
const loader = this.loader;
|
|
748
714
|
|
|
715
|
+
// final results
|
|
749
716
|
const faces = [];
|
|
750
717
|
const lineSegments = [];
|
|
751
718
|
const conditionalSegments = [];
|
|
752
719
|
const subobjects = [];
|
|
753
720
|
const materials = {};
|
|
754
|
-
|
|
755
721
|
const getLocalMaterial = colorCode => {
|
|
756
722
|
|
|
757
723
|
return materials[ colorCode ] || null;
|
|
@@ -761,8 +727,10 @@
|
|
|
761
727
|
let type = 'Model';
|
|
762
728
|
let category = null;
|
|
763
729
|
let keywords = null;
|
|
764
|
-
let
|
|
730
|
+
let author = null;
|
|
731
|
+
let totalFaces = 0;
|
|
765
732
|
|
|
733
|
+
// split into lines
|
|
766
734
|
if ( text.indexOf( '\r\n' ) !== - 1 ) {
|
|
767
735
|
|
|
768
736
|
// This is faster than String.split with regex that splits on both
|
|
@@ -779,20 +747,21 @@
|
|
|
779
747
|
let bfcCCW = true;
|
|
780
748
|
let bfcInverted = false;
|
|
781
749
|
let bfcCull = true;
|
|
782
|
-
let
|
|
750
|
+
let startingBuildingStep = false;
|
|
783
751
|
|
|
752
|
+
// Parse all line commands
|
|
784
753
|
for ( let lineIndex = 0; lineIndex < numLines; lineIndex ++ ) {
|
|
785
754
|
|
|
786
755
|
const line = lines[ lineIndex ];
|
|
787
756
|
if ( line.length === 0 ) continue;
|
|
788
|
-
|
|
789
757
|
if ( parsingEmbeddedFiles ) {
|
|
790
758
|
|
|
791
759
|
if ( line.startsWith( '0 FILE ' ) ) {
|
|
792
760
|
|
|
793
761
|
// Save previous embedded file in the cache
|
|
794
|
-
this.setData( currentEmbeddedFileName, currentEmbeddedText );
|
|
762
|
+
this.setData( currentEmbeddedFileName, currentEmbeddedText );
|
|
795
763
|
|
|
764
|
+
// New embedded text file
|
|
796
765
|
currentEmbeddedFileName = line.substring( 7 );
|
|
797
766
|
currentEmbeddedText = '';
|
|
798
767
|
|
|
@@ -808,15 +777,14 @@
|
|
|
808
777
|
|
|
809
778
|
const lp = new LineParser( line, lineIndex + 1 );
|
|
810
779
|
lp.seekNonSpace();
|
|
811
|
-
|
|
812
780
|
if ( lp.isAtTheEnd() ) {
|
|
813
781
|
|
|
814
782
|
// Empty line
|
|
815
783
|
continue;
|
|
816
784
|
|
|
817
|
-
}
|
|
818
|
-
|
|
785
|
+
}
|
|
819
786
|
|
|
787
|
+
// Parse the line type
|
|
820
788
|
const lineType = lp.getToken();
|
|
821
789
|
let material;
|
|
822
790
|
let colorCode;
|
|
@@ -824,14 +792,12 @@
|
|
|
824
792
|
let ccw;
|
|
825
793
|
let doubleSided;
|
|
826
794
|
let v0, v1, v2, v3, c0, c1;
|
|
827
|
-
|
|
828
795
|
switch ( lineType ) {
|
|
829
796
|
|
|
830
797
|
// Line type 0: Comment or META
|
|
831
798
|
case '0':
|
|
832
799
|
// Parse meta directive
|
|
833
800
|
const meta = lp.getToken();
|
|
834
|
-
|
|
835
801
|
if ( meta ) {
|
|
836
802
|
|
|
837
803
|
switch ( meta ) {
|
|
@@ -839,10 +805,8 @@
|
|
|
839
805
|
case '!LDRAW_ORG':
|
|
840
806
|
type = lp.getToken();
|
|
841
807
|
break;
|
|
842
|
-
|
|
843
808
|
case '!COLOUR':
|
|
844
809
|
material = loader.parseColorMetaDirective( lp );
|
|
845
|
-
|
|
846
810
|
if ( material ) {
|
|
847
811
|
|
|
848
812
|
materials[ material.userData.code ] = material;
|
|
@@ -854,14 +818,11 @@
|
|
|
854
818
|
}
|
|
855
819
|
|
|
856
820
|
break;
|
|
857
|
-
|
|
858
821
|
case '!CATEGORY':
|
|
859
822
|
category = lp.getToken();
|
|
860
823
|
break;
|
|
861
|
-
|
|
862
824
|
case '!KEYWORDS':
|
|
863
825
|
const newKeywords = lp.getRemainingString().split( ',' );
|
|
864
|
-
|
|
865
826
|
if ( newKeywords.length > 0 ) {
|
|
866
827
|
|
|
867
828
|
if ( ! keywords ) {
|
|
@@ -879,7 +840,6 @@
|
|
|
879
840
|
}
|
|
880
841
|
|
|
881
842
|
break;
|
|
882
|
-
|
|
883
843
|
case 'FILE':
|
|
884
844
|
if ( lineIndex > 0 ) {
|
|
885
845
|
|
|
@@ -893,13 +853,11 @@
|
|
|
893
853
|
}
|
|
894
854
|
|
|
895
855
|
break;
|
|
896
|
-
|
|
897
856
|
case 'BFC':
|
|
898
857
|
// Changes to the backface culling state
|
|
899
858
|
while ( ! lp.isAtTheEnd() ) {
|
|
900
859
|
|
|
901
860
|
const token = lp.getToken();
|
|
902
|
-
|
|
903
861
|
switch ( token ) {
|
|
904
862
|
|
|
905
863
|
case 'CERTIFY':
|
|
@@ -907,21 +865,17 @@
|
|
|
907
865
|
bfcCertified = token === 'CERTIFY';
|
|
908
866
|
bfcCCW = true;
|
|
909
867
|
break;
|
|
910
|
-
|
|
911
868
|
case 'CW':
|
|
912
869
|
case 'CCW':
|
|
913
870
|
bfcCCW = token === 'CCW';
|
|
914
871
|
break;
|
|
915
|
-
|
|
916
872
|
case 'INVERTNEXT':
|
|
917
873
|
bfcInverted = true;
|
|
918
874
|
break;
|
|
919
|
-
|
|
920
875
|
case 'CLIP':
|
|
921
876
|
case 'NOCLIP':
|
|
922
877
|
bfcCull = token === 'CLIP';
|
|
923
878
|
break;
|
|
924
|
-
|
|
925
879
|
default:
|
|
926
880
|
console.warn( 'THREE.LDrawLoader: BFC directive "' + token + '" is unknown.' );
|
|
927
881
|
break;
|
|
@@ -931,11 +885,12 @@
|
|
|
931
885
|
}
|
|
932
886
|
|
|
933
887
|
break;
|
|
934
|
-
|
|
935
888
|
case 'STEP':
|
|
936
|
-
|
|
889
|
+
startingBuildingStep = true;
|
|
890
|
+
break;
|
|
891
|
+
case 'Author:':
|
|
892
|
+
author = lp.getToken();
|
|
937
893
|
break;
|
|
938
|
-
|
|
939
894
|
default:
|
|
940
895
|
// Other meta directives are not implemented
|
|
941
896
|
break;
|
|
@@ -945,8 +900,8 @@
|
|
|
945
900
|
}
|
|
946
901
|
|
|
947
902
|
break;
|
|
948
|
-
// Line type 1: Sub-object file
|
|
949
903
|
|
|
904
|
+
// Line type 1: Sub-object file
|
|
950
905
|
case '1':
|
|
951
906
|
colorCode = lp.getToken();
|
|
952
907
|
material = getLocalMaterial( colorCode );
|
|
@@ -964,7 +919,6 @@
|
|
|
964
919
|
const m8 = parseFloat( lp.getToken() );
|
|
965
920
|
const matrix = new THREE.Matrix4().set( m0, m1, m2, posX, m3, m4, m5, posY, m6, m7, m8, posZ, 0, 0, 0, 1 );
|
|
966
921
|
let fileName = lp.getRemainingString().trim().replace( /\\/g, '/' );
|
|
967
|
-
|
|
968
922
|
if ( loader.fileMap[ fileName ] ) {
|
|
969
923
|
|
|
970
924
|
// Found the subobject path in the preloaded file path map
|
|
@@ -991,12 +945,13 @@
|
|
|
991
945
|
matrix: matrix,
|
|
992
946
|
fileName: fileName,
|
|
993
947
|
inverted: bfcInverted,
|
|
994
|
-
|
|
948
|
+
startingBuildingStep: startingBuildingStep
|
|
995
949
|
} );
|
|
950
|
+
startingBuildingStep = false;
|
|
996
951
|
bfcInverted = false;
|
|
997
952
|
break;
|
|
998
|
-
// Line type 2: Line segment
|
|
999
953
|
|
|
954
|
+
// Line type 2: Line segment
|
|
1000
955
|
case '2':
|
|
1001
956
|
colorCode = lp.getToken();
|
|
1002
957
|
material = getLocalMaterial( colorCode );
|
|
@@ -1009,8 +964,8 @@
|
|
|
1009
964
|
};
|
|
1010
965
|
lineSegments.push( segment );
|
|
1011
966
|
break;
|
|
1012
|
-
// Line type 5: Conditional Line segment
|
|
1013
967
|
|
|
968
|
+
// Line type 5: Conditional Line segment
|
|
1014
969
|
case '5':
|
|
1015
970
|
colorCode = lp.getToken();
|
|
1016
971
|
material = getLocalMaterial( colorCode );
|
|
@@ -1026,14 +981,13 @@
|
|
|
1026
981
|
};
|
|
1027
982
|
conditionalSegments.push( segment );
|
|
1028
983
|
break;
|
|
1029
|
-
// Line type 3: Triangle
|
|
1030
984
|
|
|
985
|
+
// Line type 3: Triangle
|
|
1031
986
|
case '3':
|
|
1032
987
|
colorCode = lp.getToken();
|
|
1033
988
|
material = getLocalMaterial( colorCode );
|
|
1034
989
|
ccw = bfcCCW;
|
|
1035
990
|
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1036
|
-
|
|
1037
991
|
if ( ccw === true ) {
|
|
1038
992
|
|
|
1039
993
|
v0 = lp.getVector();
|
|
@@ -1056,7 +1010,6 @@
|
|
|
1056
1010
|
normals: [ null, null, null ]
|
|
1057
1011
|
} );
|
|
1058
1012
|
totalFaces ++;
|
|
1059
|
-
|
|
1060
1013
|
if ( doubleSided === true ) {
|
|
1061
1014
|
|
|
1062
1015
|
faces.push( {
|
|
@@ -1071,14 +1024,13 @@
|
|
|
1071
1024
|
}
|
|
1072
1025
|
|
|
1073
1026
|
break;
|
|
1074
|
-
// Line type 4: Quadrilateral
|
|
1075
1027
|
|
|
1028
|
+
// Line type 4: Quadrilateral
|
|
1076
1029
|
case '4':
|
|
1077
1030
|
colorCode = lp.getToken();
|
|
1078
1031
|
material = getLocalMaterial( colorCode );
|
|
1079
1032
|
ccw = bfcCCW;
|
|
1080
1033
|
doubleSided = ! bfcCertified || ! bfcCull;
|
|
1081
|
-
|
|
1082
1034
|
if ( ccw === true ) {
|
|
1083
1035
|
|
|
1084
1036
|
v0 = lp.getVector();
|
|
@@ -1093,10 +1045,10 @@
|
|
|
1093
1045
|
v1 = lp.getVector();
|
|
1094
1046
|
v0 = lp.getVector();
|
|
1095
1047
|
|
|
1096
|
-
}
|
|
1097
|
-
// account for the doubling of vertices later when smoothing normals.
|
|
1098
|
-
|
|
1048
|
+
}
|
|
1099
1049
|
|
|
1050
|
+
// specifically place the triangle diagonal in the v0 and v1 slots so we can
|
|
1051
|
+
// account for the doubling of vertices later when smoothing normals.
|
|
1100
1052
|
faces.push( {
|
|
1101
1053
|
material: material,
|
|
1102
1054
|
colorCode: colorCode,
|
|
@@ -1105,7 +1057,6 @@
|
|
|
1105
1057
|
normals: [ null, null, null, null ]
|
|
1106
1058
|
} );
|
|
1107
1059
|
totalFaces += 2;
|
|
1108
|
-
|
|
1109
1060
|
if ( doubleSided === true ) {
|
|
1110
1061
|
|
|
1111
1062
|
faces.push( {
|
|
@@ -1120,7 +1071,6 @@
|
|
|
1120
1071
|
}
|
|
1121
1072
|
|
|
1122
1073
|
break;
|
|
1123
|
-
|
|
1124
1074
|
default:
|
|
1125
1075
|
throw new Error( 'LDrawLoader: Unknown line type "' + lineType + '"' + lp.getLineNumberString() + '.' );
|
|
1126
1076
|
|
|
@@ -1141,22 +1091,22 @@
|
|
|
1141
1091
|
type,
|
|
1142
1092
|
category,
|
|
1143
1093
|
keywords,
|
|
1094
|
+
author,
|
|
1144
1095
|
subobjects,
|
|
1145
1096
|
totalFaces,
|
|
1146
|
-
|
|
1097
|
+
startingBuildingStep,
|
|
1147
1098
|
materials,
|
|
1148
1099
|
fileName,
|
|
1149
1100
|
group: null
|
|
1150
1101
|
};
|
|
1151
1102
|
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1103
|
+
}
|
|
1154
1104
|
|
|
1105
|
+
// returns an (optionally cloned) instance of the data
|
|
1155
1106
|
getData( fileName, clone = true ) {
|
|
1156
1107
|
|
|
1157
1108
|
const key = fileName.toLowerCase();
|
|
1158
1109
|
const result = this._cache[ key ];
|
|
1159
|
-
|
|
1160
1110
|
if ( result === null || result instanceof Promise ) {
|
|
1161
1111
|
|
|
1162
1112
|
return null;
|
|
@@ -1173,14 +1123,13 @@
|
|
|
1173
1123
|
|
|
1174
1124
|
}
|
|
1175
1125
|
|
|
1176
|
-
}
|
|
1177
|
-
// the data is ready to use and can be retrieved synchronously with "getData".
|
|
1178
|
-
|
|
1126
|
+
}
|
|
1179
1127
|
|
|
1128
|
+
// kicks off a fetch and parse of the requested data if it hasn't already been loaded. Returns when
|
|
1129
|
+
// the data is ready to use and can be retrieved synchronously with "getData".
|
|
1180
1130
|
async ensureDataLoaded( fileName ) {
|
|
1181
1131
|
|
|
1182
1132
|
const key = fileName.toLowerCase();
|
|
1183
|
-
|
|
1184
1133
|
if ( ! ( key in this._cache ) ) {
|
|
1185
1134
|
|
|
1186
1135
|
// replace the promise with a copy of the parsed data for immediate processing
|
|
@@ -1196,9 +1145,9 @@
|
|
|
1196
1145
|
|
|
1197
1146
|
await this._cache[ key ];
|
|
1198
1147
|
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1148
|
+
}
|
|
1201
1149
|
|
|
1150
|
+
// sets the data in the cache from parsed data
|
|
1202
1151
|
setData( fileName, text ) {
|
|
1203
1152
|
|
|
1204
1153
|
const key = fileName.toLowerCase();
|
|
@@ -1206,14 +1155,13 @@
|
|
|
1206
1155
|
|
|
1207
1156
|
}
|
|
1208
1157
|
|
|
1209
|
-
}
|
|
1210
|
-
// an edge then the passthroughColorCode is used.
|
|
1211
|
-
|
|
1158
|
+
}
|
|
1212
1159
|
|
|
1160
|
+
// returns the material for an associated color code. If the color code is 16 for a face or 24 for
|
|
1161
|
+
// an edge then the passthroughColorCode is used.
|
|
1213
1162
|
function getMaterialFromCode( colorCode, parentColorCode, materialHierarchy, forEdge ) {
|
|
1214
1163
|
|
|
1215
1164
|
const isPassthrough = ! forEdge && colorCode === MAIN_COLOUR_CODE || forEdge && colorCode === MAIN_EDGE_COLOUR_CODE;
|
|
1216
|
-
|
|
1217
1165
|
if ( isPassthrough ) {
|
|
1218
1166
|
|
|
1219
1167
|
colorCode = parentColorCode;
|
|
@@ -1222,9 +1170,9 @@
|
|
|
1222
1170
|
|
|
1223
1171
|
return materialHierarchy[ colorCode ] || null;
|
|
1224
1172
|
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1173
|
+
}
|
|
1227
1174
|
|
|
1175
|
+
// Class used to parse and build LDraw parts as three.js objects and cache them if they're a "Part" type.
|
|
1228
1176
|
class LDrawPartsGeometryCache {
|
|
1229
1177
|
|
|
1230
1178
|
constructor( loader ) {
|
|
@@ -1233,29 +1181,30 @@
|
|
|
1233
1181
|
this.parseCache = new LDrawParsedCache( loader );
|
|
1234
1182
|
this._cache = {};
|
|
1235
1183
|
|
|
1236
|
-
}
|
|
1237
|
-
|
|
1184
|
+
}
|
|
1238
1185
|
|
|
1186
|
+
// Convert the given file information into a mesh by processing subobjects.
|
|
1239
1187
|
async processIntoMesh( info ) {
|
|
1240
1188
|
|
|
1241
1189
|
const loader = this.loader;
|
|
1242
1190
|
const parseCache = this.parseCache;
|
|
1243
|
-
const faceMaterials = new Set();
|
|
1244
|
-
// piece object.
|
|
1191
|
+
const faceMaterials = new Set();
|
|
1245
1192
|
|
|
1193
|
+
// Processes the part subobject information to load child parts and merge geometry onto part
|
|
1194
|
+
// piece object.
|
|
1246
1195
|
const processInfoSubobjects = async ( info, subobject = null ) => {
|
|
1247
1196
|
|
|
1248
1197
|
const subobjects = info.subobjects;
|
|
1249
|
-
const promises = [];
|
|
1250
|
-
// group which lets instruction steps apply correctly.
|
|
1198
|
+
const promises = [];
|
|
1251
1199
|
|
|
1200
|
+
// Trigger load of all subobjects. If a subobject isn't a primitive then load it as a separate
|
|
1201
|
+
// group which lets instruction steps apply correctly.
|
|
1252
1202
|
for ( let i = 0, l = subobjects.length; i < l; i ++ ) {
|
|
1253
1203
|
|
|
1254
1204
|
const subobject = subobjects[ i ];
|
|
1255
1205
|
const promise = parseCache.ensureDataLoaded( subobject.fileName ).then( () => {
|
|
1256
1206
|
|
|
1257
1207
|
const subobjectInfo = parseCache.getData( subobject.fileName, false );
|
|
1258
|
-
|
|
1259
1208
|
if ( ! isPrimitiveType( subobjectInfo.type ) ) {
|
|
1260
1209
|
|
|
1261
1210
|
return this.loadModel( subobject.fileName ).catch( error => {
|
|
@@ -1277,43 +1226,45 @@
|
|
|
1277
1226
|
const group = new THREE.Group();
|
|
1278
1227
|
group.userData.category = info.category;
|
|
1279
1228
|
group.userData.keywords = info.keywords;
|
|
1229
|
+
group.userData.author = info.author;
|
|
1230
|
+
group.userData.type = info.type;
|
|
1231
|
+
group.userData.fileName = info.fileName;
|
|
1280
1232
|
info.group = group;
|
|
1281
1233
|
const subobjectInfos = await Promise.all( promises );
|
|
1282
|
-
|
|
1283
1234
|
for ( let i = 0, l = subobjectInfos.length; i < l; i ++ ) {
|
|
1284
1235
|
|
|
1285
1236
|
const subobject = info.subobjects[ i ];
|
|
1286
1237
|
const subobjectInfo = subobjectInfos[ i ];
|
|
1287
|
-
|
|
1288
1238
|
if ( subobjectInfo === null ) {
|
|
1289
1239
|
|
|
1290
1240
|
// the subobject failed to load
|
|
1291
1241
|
continue;
|
|
1292
1242
|
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1243
|
+
}
|
|
1295
1244
|
|
|
1245
|
+
// if the subobject was loaded as a separate group then apply the parent scopes materials
|
|
1296
1246
|
if ( subobjectInfo.isGroup ) {
|
|
1297
1247
|
|
|
1298
1248
|
const subobjectGroup = subobjectInfo;
|
|
1299
1249
|
subobject.matrix.decompose( subobjectGroup.position, subobjectGroup.quaternion, subobjectGroup.scale );
|
|
1300
|
-
subobjectGroup.userData.
|
|
1250
|
+
subobjectGroup.userData.startingBuildingStep = subobject.startingBuildingStep;
|
|
1301
1251
|
subobjectGroup.name = subobject.fileName;
|
|
1302
1252
|
loader.applyMaterialsToMesh( subobjectGroup, subobject.colorCode, info.materials );
|
|
1253
|
+
subobjectGroup.userData.colorCode = subobject.colorCode;
|
|
1303
1254
|
group.add( subobjectGroup );
|
|
1304
1255
|
continue;
|
|
1305
1256
|
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1257
|
+
}
|
|
1308
1258
|
|
|
1259
|
+
// add the subobject group if it has children in case it has both children and primitives
|
|
1309
1260
|
if ( subobjectInfo.group.children.length ) {
|
|
1310
1261
|
|
|
1311
1262
|
group.add( subobjectInfo.group );
|
|
1312
1263
|
|
|
1313
|
-
}
|
|
1314
|
-
// to the parent primitives list.
|
|
1315
|
-
|
|
1264
|
+
}
|
|
1316
1265
|
|
|
1266
|
+
// transform the primitives into the local space of the parent piece and append them to
|
|
1267
|
+
// to the parent primitives list.
|
|
1317
1268
|
const parentLineSegments = info.lineSegments;
|
|
1318
1269
|
const parentConditionalSegments = info.conditionalSegments;
|
|
1319
1270
|
const parentFaces = info.faces;
|
|
@@ -1325,7 +1276,6 @@
|
|
|
1325
1276
|
const matrixScaleInverted = matrix.determinant() < 0;
|
|
1326
1277
|
const colorCode = subobject.colorCode;
|
|
1327
1278
|
const lineColorCode = colorCode === MAIN_COLOUR_CODE ? MAIN_EDGE_COLOUR_CODE : colorCode;
|
|
1328
|
-
|
|
1329
1279
|
for ( let i = 0, l = lineSegments.length; i < l; i ++ ) {
|
|
1330
1280
|
|
|
1331
1281
|
const ls = lineSegments[ i ];
|
|
@@ -1357,7 +1307,6 @@
|
|
|
1357
1307
|
|
|
1358
1308
|
const tri = faces[ i ];
|
|
1359
1309
|
const vertices = tri.vertices;
|
|
1360
|
-
|
|
1361
1310
|
for ( let i = 0, l = vertices.length; i < l; i ++ ) {
|
|
1362
1311
|
|
|
1363
1312
|
vertices[ i ].applyMatrix4( matrix );
|
|
@@ -1366,9 +1315,10 @@
|
|
|
1366
1315
|
|
|
1367
1316
|
tri.colorCode = tri.colorCode === MAIN_COLOUR_CODE ? colorCode : tri.colorCode;
|
|
1368
1317
|
tri.material = tri.material || getMaterialFromCode( tri.colorCode, colorCode, info.materials, false );
|
|
1369
|
-
faceMaterials.add( tri.colorCode );
|
|
1370
|
-
// needs to be flipped.
|
|
1318
|
+
faceMaterials.add( tri.colorCode );
|
|
1371
1319
|
|
|
1320
|
+
// If the scale of the object is negated then the triangle winding order
|
|
1321
|
+
// needs to be flipped.
|
|
1372
1322
|
if ( matrixScaleInverted !== inverted ) {
|
|
1373
1323
|
|
|
1374
1324
|
vertices.reverse();
|
|
@@ -1381,21 +1331,22 @@
|
|
|
1381
1331
|
|
|
1382
1332
|
info.totalFaces += subobjectInfo.totalFaces;
|
|
1383
1333
|
|
|
1384
|
-
}
|
|
1385
|
-
// to material scoping.
|
|
1386
|
-
|
|
1334
|
+
}
|
|
1387
1335
|
|
|
1336
|
+
// Apply the parent subobjects pass through material code to this object. This is done several times due
|
|
1337
|
+
// to material scoping.
|
|
1388
1338
|
if ( subobject ) {
|
|
1389
1339
|
|
|
1390
1340
|
loader.applyMaterialsToMesh( group, subobject.colorCode, info.materials );
|
|
1341
|
+
group.userData.colorCode = subobject.colorCode;
|
|
1391
1342
|
|
|
1392
1343
|
}
|
|
1393
1344
|
|
|
1394
1345
|
return info;
|
|
1395
1346
|
|
|
1396
|
-
};
|
|
1397
|
-
|
|
1347
|
+
};
|
|
1398
1348
|
|
|
1349
|
+
// Track material use to see if we need to use the normal smooth slow path for hard edges.
|
|
1399
1350
|
for ( let i = 0, l = info.faces; i < l; i ++ ) {
|
|
1400
1351
|
|
|
1401
1352
|
faceMaterials.add( info.faces[ i ].colorCode );
|
|
@@ -1403,18 +1354,16 @@
|
|
|
1403
1354
|
}
|
|
1404
1355
|
|
|
1405
1356
|
await processInfoSubobjects( info );
|
|
1406
|
-
|
|
1407
1357
|
if ( loader.smoothNormals ) {
|
|
1408
1358
|
|
|
1409
1359
|
const checkSubSegments = faceMaterials.size > 1;
|
|
1410
1360
|
generateFaceNormals( info.faces );
|
|
1411
1361
|
smoothNormals( info.faces, info.lineSegments, checkSubSegments );
|
|
1412
1362
|
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1363
|
+
}
|
|
1415
1364
|
|
|
1365
|
+
// Add the primitive objects and metadata.
|
|
1416
1366
|
const group = info.group;
|
|
1417
|
-
|
|
1418
1367
|
if ( info.faces.length > 0 ) {
|
|
1419
1368
|
|
|
1420
1369
|
group.add( createObject( info.faces, 3, false, info.totalFaces ) );
|
|
@@ -1436,13 +1385,11 @@
|
|
|
1436
1385
|
return group;
|
|
1437
1386
|
|
|
1438
1387
|
}
|
|
1439
|
-
|
|
1440
1388
|
hasCachedModel( fileName ) {
|
|
1441
1389
|
|
|
1442
1390
|
return fileName !== null && fileName.toLowerCase() in this._cache;
|
|
1443
1391
|
|
|
1444
1392
|
}
|
|
1445
|
-
|
|
1446
1393
|
async getCachedModel( fileName ) {
|
|
1447
1394
|
|
|
1448
1395
|
if ( fileName !== null && this.hasCachedModel( fileName ) ) {
|
|
@@ -1457,14 +1404,13 @@
|
|
|
1457
1404
|
|
|
1458
1405
|
}
|
|
1459
1406
|
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1407
|
+
}
|
|
1462
1408
|
|
|
1409
|
+
// Loads and parses the model with the given file name. Returns a cached copy if available.
|
|
1463
1410
|
async loadModel( fileName ) {
|
|
1464
1411
|
|
|
1465
1412
|
const parseCache = this.parseCache;
|
|
1466
1413
|
const key = fileName.toLowerCase();
|
|
1467
|
-
|
|
1468
1414
|
if ( this.hasCachedModel( fileName ) ) {
|
|
1469
1415
|
|
|
1470
1416
|
// Return cached model if available.
|
|
@@ -1476,37 +1422,37 @@
|
|
|
1476
1422
|
// Ensure the file data is loaded and pre parsed.
|
|
1477
1423
|
await parseCache.ensureDataLoaded( fileName );
|
|
1478
1424
|
const info = parseCache.getData( fileName );
|
|
1479
|
-
const promise = this.processIntoMesh( info );
|
|
1425
|
+
const promise = this.processIntoMesh( info );
|
|
1426
|
+
|
|
1427
|
+
// Now that the file has loaded it's possible that another part parse has been waiting in parallel
|
|
1480
1428
|
// so check the cache again to see if it's been added since the last async operation so we don't
|
|
1481
1429
|
// do unnecessary work.
|
|
1482
|
-
|
|
1483
1430
|
if ( this.hasCachedModel( fileName ) ) {
|
|
1484
1431
|
|
|
1485
1432
|
return this.getCachedModel( fileName );
|
|
1486
1433
|
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1434
|
+
}
|
|
1489
1435
|
|
|
1436
|
+
// Cache object if it's a part so it can be reused later.
|
|
1490
1437
|
if ( isPartType( info.type ) ) {
|
|
1491
1438
|
|
|
1492
1439
|
this._cache[ key ] = promise;
|
|
1493
1440
|
|
|
1494
|
-
}
|
|
1495
|
-
|
|
1441
|
+
}
|
|
1496
1442
|
|
|
1443
|
+
// return a copy
|
|
1497
1444
|
const group = await promise;
|
|
1498
1445
|
return group.clone();
|
|
1499
1446
|
|
|
1500
1447
|
}
|
|
1501
1448
|
|
|
1502
|
-
}
|
|
1503
|
-
|
|
1449
|
+
}
|
|
1504
1450
|
|
|
1451
|
+
// parses the given model text into a renderable object. Returns cached copy if available.
|
|
1505
1452
|
async parseModel( text ) {
|
|
1506
1453
|
|
|
1507
1454
|
const parseCache = this.parseCache;
|
|
1508
1455
|
const info = parseCache.parse( text );
|
|
1509
|
-
|
|
1510
1456
|
if ( isPartType( info.type ) && this.hasCachedModel( info.fileName ) ) {
|
|
1511
1457
|
|
|
1512
1458
|
return this.getCachedModel( info.fileName );
|
|
@@ -1518,7 +1464,6 @@
|
|
|
1518
1464
|
}
|
|
1519
1465
|
|
|
1520
1466
|
}
|
|
1521
|
-
|
|
1522
1467
|
function sortByMaterial( a, b ) {
|
|
1523
1468
|
|
|
1524
1469
|
if ( a.colorCode === b.colorCode ) {
|
|
@@ -1541,9 +1486,9 @@
|
|
|
1541
1486
|
|
|
1542
1487
|
// Creates a THREE.LineSegments (elementSize = 2) or a THREE.Mesh (elementSize = 3 )
|
|
1543
1488
|
// With per face / segment material, implemented with mesh groups and materials array
|
|
1489
|
+
|
|
1544
1490
|
// Sort the faces or line segments by color code to make later the mesh groups
|
|
1545
1491
|
elements.sort( sortByMaterial );
|
|
1546
|
-
|
|
1547
1492
|
if ( totalElements === null ) {
|
|
1548
1493
|
|
|
1549
1494
|
totalElements = elements.length;
|
|
@@ -1559,12 +1504,10 @@
|
|
|
1559
1504
|
let index0 = 0;
|
|
1560
1505
|
let numGroupVerts = 0;
|
|
1561
1506
|
let offset = 0;
|
|
1562
|
-
|
|
1563
1507
|
for ( let iElem = 0, nElem = elements.length; iElem < nElem; iElem ++ ) {
|
|
1564
1508
|
|
|
1565
1509
|
const elem = elements[ iElem ];
|
|
1566
1510
|
let vertices = elem.vertices;
|
|
1567
|
-
|
|
1568
1511
|
if ( vertices.length === 4 ) {
|
|
1569
1512
|
|
|
1570
1513
|
quadArray[ 0 ] = vertices[ 0 ];
|
|
@@ -1585,9 +1528,9 @@
|
|
|
1585
1528
|
positions[ index + 1 ] = v.y;
|
|
1586
1529
|
positions[ index + 2 ] = v.z;
|
|
1587
1530
|
|
|
1588
|
-
}
|
|
1589
|
-
|
|
1531
|
+
}
|
|
1590
1532
|
|
|
1533
|
+
// create the normals array if this is a set of faces
|
|
1591
1534
|
if ( elementSize === 3 ) {
|
|
1592
1535
|
|
|
1593
1536
|
if ( ! elem.faceNormal ) {
|
|
@@ -1595,17 +1538,13 @@
|
|
|
1595
1538
|
const v0 = vertices[ 0 ];
|
|
1596
1539
|
const v1 = vertices[ 1 ];
|
|
1597
1540
|
const v2 = vertices[ 2 ];
|
|
1598
|
-
|
|
1599
1541
|
_tempVec0.subVectors( v1, v0 );
|
|
1600
|
-
|
|
1601
1542
|
_tempVec1.subVectors( v2, v1 );
|
|
1602
|
-
|
|
1603
1543
|
elem.faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize();
|
|
1604
1544
|
|
|
1605
1545
|
}
|
|
1606
1546
|
|
|
1607
1547
|
let elemNormals = elem.normals;
|
|
1608
|
-
|
|
1609
1548
|
if ( elemNormals.length === 4 ) {
|
|
1610
1549
|
|
|
1611
1550
|
quadArray[ 0 ] = elemNormals[ 0 ];
|
|
@@ -1622,7 +1561,6 @@
|
|
|
1622
1561
|
|
|
1623
1562
|
// use face normal if a vertex normal is not provided
|
|
1624
1563
|
let n = elem.faceNormal;
|
|
1625
|
-
|
|
1626
1564
|
if ( elemNormals[ j ] ) {
|
|
1627
1565
|
|
|
1628
1566
|
n = elemNormals[ j ].norm;
|
|
@@ -1647,7 +1585,6 @@
|
|
|
1647
1585
|
}
|
|
1648
1586
|
|
|
1649
1587
|
const material = elem.material;
|
|
1650
|
-
|
|
1651
1588
|
if ( material !== null ) {
|
|
1652
1589
|
|
|
1653
1590
|
if ( elementSize === 3 ) {
|
|
@@ -1697,7 +1634,6 @@
|
|
|
1697
1634
|
}
|
|
1698
1635
|
|
|
1699
1636
|
bufferGeometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
|
|
1700
|
-
|
|
1701
1637
|
if ( normals !== null ) {
|
|
1702
1638
|
|
|
1703
1639
|
bufferGeometry.setAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
|
|
@@ -1705,7 +1641,6 @@
|
|
|
1705
1641
|
}
|
|
1706
1642
|
|
|
1707
1643
|
let object3d = null;
|
|
1708
|
-
|
|
1709
1644
|
if ( elementSize === 2 ) {
|
|
1710
1645
|
|
|
1711
1646
|
if ( isConditionalSegments ) {
|
|
@@ -1730,7 +1665,6 @@
|
|
|
1730
1665
|
const controlArray0 = new Float32Array( elements.length * 3 * 2 );
|
|
1731
1666
|
const controlArray1 = new Float32Array( elements.length * 3 * 2 );
|
|
1732
1667
|
const directionArray = new Float32Array( elements.length * 3 * 2 );
|
|
1733
|
-
|
|
1734
1668
|
for ( let i = 0, l = elements.length; i < l; i ++ ) {
|
|
1735
1669
|
|
|
1736
1670
|
const os = elements[ i ];
|
|
@@ -1770,37 +1704,61 @@
|
|
|
1770
1704
|
|
|
1771
1705
|
return object3d;
|
|
1772
1706
|
|
|
1773
|
-
}
|
|
1707
|
+
}
|
|
1774
1708
|
|
|
1709
|
+
//
|
|
1775
1710
|
|
|
1776
1711
|
class LDrawLoader extends THREE.Loader {
|
|
1777
1712
|
|
|
1778
1713
|
constructor( manager ) {
|
|
1779
1714
|
|
|
1780
|
-
super( manager );
|
|
1715
|
+
super( manager );
|
|
1781
1716
|
|
|
1717
|
+
// Array of THREE.Material
|
|
1782
1718
|
this.materials = [];
|
|
1783
|
-
this.materialLibrary = {};
|
|
1719
|
+
this.materialLibrary = {};
|
|
1784
1720
|
|
|
1785
|
-
|
|
1721
|
+
// This also allows to handle the embedded text files ("0 FILE" lines)
|
|
1722
|
+
this.partsCache = new LDrawPartsGeometryCache( this );
|
|
1786
1723
|
|
|
1787
|
-
|
|
1724
|
+
// This object is a map from file names to paths. It agilizes the paths search. If it is not set then files will be searched by trial and error.
|
|
1725
|
+
this.fileMap = {};
|
|
1788
1726
|
|
|
1789
|
-
|
|
1727
|
+
// Initializes the materials library with default materials
|
|
1728
|
+
this.setMaterials( [] );
|
|
1790
1729
|
|
|
1791
|
-
|
|
1730
|
+
// If this flag is set to true the vertex normals will be smoothed.
|
|
1731
|
+
this.smoothNormals = true;
|
|
1792
1732
|
|
|
1733
|
+
// The path to load parts from the LDraw parts library from.
|
|
1793
1734
|
this.partsLibraryPath = '';
|
|
1794
1735
|
|
|
1795
|
-
|
|
1736
|
+
// Material assigned to not available colors for meshes and edges
|
|
1737
|
+
this.missingColorMaterial = new THREE.MeshStandardMaterial( {
|
|
1738
|
+
color: 0xFF00FF,
|
|
1739
|
+
roughness: 0.3,
|
|
1740
|
+
metalness: 0
|
|
1741
|
+
} );
|
|
1742
|
+
this.missingColorMaterial.name = 'Missing material';
|
|
1743
|
+
this.missingEdgeColorMaterial = new THREE.LineBasicMaterial( {
|
|
1744
|
+
color: 0xFF00FF
|
|
1745
|
+
} );
|
|
1746
|
+
this.missingEdgeColorMaterial.name = 'Missing material - Edge';
|
|
1747
|
+
this.missingConditionalEdgeColorMaterial = new LDrawConditionalLineMaterial( {
|
|
1748
|
+
fog: true,
|
|
1749
|
+
color: 0xFF00FF
|
|
1750
|
+
} );
|
|
1751
|
+
this.missingConditionalEdgeColorMaterial.name = 'Missing material - Conditional Edge';
|
|
1752
|
+
this.missingColorMaterial.userData.edgeMaterial = this.missingEdgeColorMaterial;
|
|
1753
|
+
this.missingEdgeColorMaterial.userData.conditionalEdgeMaterial = this.missingConditionalEdgeColorMaterial;
|
|
1796
1754
|
|
|
1755
|
+
}
|
|
1797
1756
|
setPartsLibraryPath( path ) {
|
|
1798
1757
|
|
|
1799
1758
|
this.partsLibraryPath = path;
|
|
1800
1759
|
return this;
|
|
1801
1760
|
|
|
1802
1761
|
}
|
|
1803
|
-
|
|
1804
1762
|
async preloadMaterials( url ) {
|
|
1805
1763
|
|
|
1806
1764
|
const fileLoader = new THREE.FileLoader( this.manager );
|
|
@@ -1811,11 +1769,9 @@
|
|
|
1811
1769
|
const colorLineRegex = /^0 !COLOUR/;
|
|
1812
1770
|
const lines = text.split( /[\n\r]/g );
|
|
1813
1771
|
const materials = [];
|
|
1814
|
-
|
|
1815
1772
|
for ( let i = 0, l = lines.length; i < l; i ++ ) {
|
|
1816
1773
|
|
|
1817
1774
|
const line = lines[ i ];
|
|
1818
|
-
|
|
1819
1775
|
if ( colorLineRegex.test( line ) ) {
|
|
1820
1776
|
|
|
1821
1777
|
const directive = line.replace( colorLineRegex, '' );
|
|
@@ -1829,7 +1785,6 @@
|
|
|
1829
1785
|
this.setMaterials( materials );
|
|
1830
1786
|
|
|
1831
1787
|
}
|
|
1832
|
-
|
|
1833
1788
|
load( url, onLoad, onProgress, onError ) {
|
|
1834
1789
|
|
|
1835
1790
|
const fileLoader = new THREE.FileLoader( this.manager );
|
|
@@ -1841,7 +1796,8 @@
|
|
|
1841
1796
|
this.partsCache.parseModel( text, this.materialLibrary ).then( group => {
|
|
1842
1797
|
|
|
1843
1798
|
this.applyMaterialsToMesh( group, MAIN_COLOUR_CODE, this.materialLibrary, true );
|
|
1844
|
-
this.
|
|
1799
|
+
this.computeBuildingSteps( group );
|
|
1800
|
+
group.userData.fileName = url;
|
|
1845
1801
|
onLoad( group );
|
|
1846
1802
|
|
|
1847
1803
|
} ).catch( onError );
|
|
@@ -1849,48 +1805,45 @@
|
|
|
1849
1805
|
}, onProgress, onError );
|
|
1850
1806
|
|
|
1851
1807
|
}
|
|
1852
|
-
|
|
1853
1808
|
parse( text, onLoad ) {
|
|
1854
1809
|
|
|
1855
1810
|
this.partsCache.parseModel( text, this.materialLibrary ).then( group => {
|
|
1856
1811
|
|
|
1857
|
-
this.
|
|
1812
|
+
this.applyMaterialsToMesh( group, MAIN_COLOUR_CODE, this.materialLibrary, true );
|
|
1813
|
+
this.computeBuildingSteps( group );
|
|
1814
|
+
group.userData.fileName = '';
|
|
1858
1815
|
onLoad( group );
|
|
1859
1816
|
|
|
1860
1817
|
} );
|
|
1861
1818
|
|
|
1862
1819
|
}
|
|
1863
|
-
|
|
1864
1820
|
setMaterials( materials ) {
|
|
1865
1821
|
|
|
1866
1822
|
this.materialLibrary = {};
|
|
1867
1823
|
this.materials = [];
|
|
1868
|
-
|
|
1869
1824
|
for ( let i = 0, l = materials.length; i < l; i ++ ) {
|
|
1870
1825
|
|
|
1871
1826
|
this.addMaterial( materials[ i ] );
|
|
1872
1827
|
|
|
1873
|
-
}
|
|
1874
|
-
|
|
1828
|
+
}
|
|
1875
1829
|
|
|
1830
|
+
// Add default main triangle and line edge materials (used in pieces that can be colored with a main color)
|
|
1876
1831
|
this.addMaterial( this.parseColorMetaDirective( new LineParser( 'Main_Colour CODE 16 VALUE #FF8080 EDGE #333333' ) ) );
|
|
1877
1832
|
this.addMaterial( this.parseColorMetaDirective( new LineParser( 'Edge_Colour CODE 24 VALUE #A0A0A0 EDGE #333333' ) ) );
|
|
1878
1833
|
return this;
|
|
1879
1834
|
|
|
1880
1835
|
}
|
|
1881
|
-
|
|
1882
1836
|
setFileMap( fileMap ) {
|
|
1883
1837
|
|
|
1884
1838
|
this.fileMap = fileMap;
|
|
1885
1839
|
return this;
|
|
1886
1840
|
|
|
1887
1841
|
}
|
|
1888
|
-
|
|
1889
1842
|
addMaterial( material ) {
|
|
1890
1843
|
|
|
1891
1844
|
// Adds a material to the material library which is on top of the parse scopes stack. And also to the materials array
|
|
1892
|
-
const matLib = this.materialLibrary;
|
|
1893
1845
|
|
|
1846
|
+
const matLib = this.materialLibrary;
|
|
1894
1847
|
if ( ! matLib[ material.userData.code ] ) {
|
|
1895
1848
|
|
|
1896
1849
|
this.materials.push( material );
|
|
@@ -1901,7 +1854,6 @@
|
|
|
1901
1854
|
return this;
|
|
1902
1855
|
|
|
1903
1856
|
}
|
|
1904
|
-
|
|
1905
1857
|
getMaterial( colorCode ) {
|
|
1906
1858
|
|
|
1907
1859
|
if ( colorCode.startsWith( '0x2' ) ) {
|
|
@@ -1914,10 +1866,10 @@
|
|
|
1914
1866
|
|
|
1915
1867
|
return this.materialLibrary[ colorCode ] || null;
|
|
1916
1868
|
|
|
1917
|
-
}
|
|
1918
|
-
// in the material array if they need to be filled in.
|
|
1919
|
-
|
|
1869
|
+
}
|
|
1920
1870
|
|
|
1871
|
+
// Applies the appropriate materials to a prebuilt hierarchy of geometry. Assumes that color codes are present
|
|
1872
|
+
// in the material array if they need to be filled in.
|
|
1921
1873
|
applyMaterialsToMesh( group, parentColorCode, materialHierarchy, finalMaterialPass = false ) {
|
|
1922
1874
|
|
|
1923
1875
|
// find any missing materials as indicated by a color code string and replace it with a material from the current material lib
|
|
@@ -1947,10 +1899,11 @@
|
|
|
1947
1899
|
|
|
1948
1900
|
}
|
|
1949
1901
|
|
|
1950
|
-
} );
|
|
1902
|
+
} );
|
|
1903
|
+
|
|
1904
|
+
// Returns the appropriate material for the object (line or face) given color code. If the code is "pass through"
|
|
1951
1905
|
// (24 for lines, 16 for edges) then the pass through color code is used. If that is also pass through then it's
|
|
1952
1906
|
// simply returned for the subsequent material application.
|
|
1953
|
-
|
|
1954
1907
|
function getMaterial( c, colorCode ) {
|
|
1955
1908
|
|
|
1956
1909
|
// if our parent is a passthrough color code and we don't have the current material color available then
|
|
@@ -1963,7 +1916,6 @@
|
|
|
1963
1916
|
|
|
1964
1917
|
const forEdge = c.isLineSegments || c.isConditionalLine;
|
|
1965
1918
|
const isPassthrough = ! forEdge && colorCode === MAIN_COLOUR_CODE || forEdge && colorCode === MAIN_EDGE_COLOUR_CODE;
|
|
1966
|
-
|
|
1967
1919
|
if ( isPassthrough ) {
|
|
1968
1920
|
|
|
1969
1921
|
colorCode = parentColorCode;
|
|
@@ -1971,7 +1923,6 @@
|
|
|
1971
1923
|
}
|
|
1972
1924
|
|
|
1973
1925
|
let material = null;
|
|
1974
|
-
|
|
1975
1926
|
if ( colorCode in materialHierarchy ) {
|
|
1976
1927
|
|
|
1977
1928
|
material = materialHierarchy[ colorCode ];
|
|
@@ -1981,11 +1932,13 @@
|
|
|
1981
1932
|
// see if we can get the final material from from the "getMaterial" function which will attempt to
|
|
1982
1933
|
// parse the "direct" colors
|
|
1983
1934
|
material = loader.getMaterial( colorCode );
|
|
1984
|
-
|
|
1985
1935
|
if ( material === null ) {
|
|
1986
1936
|
|
|
1987
|
-
// otherwise throw
|
|
1988
|
-
|
|
1937
|
+
// otherwise throw a warning if this is final opportunity to set the material
|
|
1938
|
+
console.warn( `LDrawLoader: Material properties for code ${colorCode} not available.` );
|
|
1939
|
+
|
|
1940
|
+
// And return the 'missing color' material
|
|
1941
|
+
material = loader.missingColorMaterial;
|
|
1989
1942
|
|
|
1990
1943
|
}
|
|
1991
1944
|
|
|
@@ -1998,7 +1951,6 @@
|
|
|
1998
1951
|
if ( c.isLineSegments ) {
|
|
1999
1952
|
|
|
2000
1953
|
material = material.userData.edgeMaterial;
|
|
2001
|
-
|
|
2002
1954
|
if ( c.isConditionalLine ) {
|
|
2003
1955
|
|
|
2004
1956
|
material = material.userData.conditionalEdgeMaterial;
|
|
@@ -2012,166 +1964,147 @@
|
|
|
2012
1964
|
}
|
|
2013
1965
|
|
|
2014
1966
|
}
|
|
2015
|
-
|
|
2016
1967
|
getMainMaterial() {
|
|
2017
1968
|
|
|
2018
1969
|
return this.getMaterial( MAIN_COLOUR_CODE );
|
|
2019
1970
|
|
|
2020
1971
|
}
|
|
2021
|
-
|
|
2022
1972
|
getMainEdgeMaterial() {
|
|
2023
1973
|
|
|
2024
|
-
const
|
|
2025
|
-
return
|
|
1974
|
+
const mat = this.getMaterial( MAIN_EDGE_COLOUR_CODE );
|
|
1975
|
+
return mat ? mat.userData.edgeMaterial : null;
|
|
2026
1976
|
|
|
2027
1977
|
}
|
|
2028
|
-
|
|
2029
1978
|
parseColorMetaDirective( lineParser ) {
|
|
2030
1979
|
|
|
2031
1980
|
// Parses a color definition and returns a THREE.Material
|
|
2032
|
-
let code = null; // Triangle and line colors
|
|
2033
1981
|
|
|
1982
|
+
let code = null;
|
|
1983
|
+
|
|
1984
|
+
// Triangle and line colors
|
|
2034
1985
|
let color = 0xFF00FF;
|
|
2035
|
-
let edgeColor = 0xFF00FF;
|
|
1986
|
+
let edgeColor = 0xFF00FF;
|
|
2036
1987
|
|
|
1988
|
+
// Transparency
|
|
2037
1989
|
let alpha = 1;
|
|
2038
|
-
let isTransparent = false;
|
|
2039
|
-
|
|
1990
|
+
let isTransparent = false;
|
|
1991
|
+
// Self-illumination:
|
|
2040
1992
|
let luminance = 0;
|
|
2041
1993
|
let finishType = FINISH_TYPE_DEFAULT;
|
|
2042
1994
|
let edgeMaterial = null;
|
|
2043
1995
|
const name = lineParser.getToken();
|
|
2044
|
-
|
|
2045
1996
|
if ( ! name ) {
|
|
2046
1997
|
|
|
2047
1998
|
throw new Error( 'LDrawLoader: Material name was expected after "!COLOUR tag' + lineParser.getLineNumberString() + '.' );
|
|
2048
1999
|
|
|
2049
|
-
}
|
|
2050
|
-
|
|
2000
|
+
}
|
|
2051
2001
|
|
|
2002
|
+
// Parse tag tokens and their parameters
|
|
2052
2003
|
let token = null;
|
|
2053
|
-
|
|
2054
2004
|
while ( true ) {
|
|
2055
2005
|
|
|
2056
2006
|
token = lineParser.getToken();
|
|
2057
|
-
|
|
2058
2007
|
if ( ! token ) {
|
|
2059
2008
|
|
|
2060
2009
|
break;
|
|
2061
2010
|
|
|
2062
2011
|
}
|
|
2063
2012
|
|
|
2064
|
-
|
|
2013
|
+
if ( ! parseLuminance( token ) ) {
|
|
2065
2014
|
|
|
2066
|
-
|
|
2067
|
-
code = lineParser.getToken();
|
|
2068
|
-
break;
|
|
2069
|
-
|
|
2070
|
-
case 'VALUE':
|
|
2071
|
-
color = lineParser.getToken();
|
|
2015
|
+
switch ( token.toUpperCase() ) {
|
|
2072
2016
|
|
|
2073
|
-
|
|
2017
|
+
case 'CODE':
|
|
2018
|
+
code = lineParser.getToken();
|
|
2019
|
+
break;
|
|
2020
|
+
case 'VALUE':
|
|
2021
|
+
color = lineParser.getToken();
|
|
2022
|
+
if ( color.startsWith( '0x' ) ) {
|
|
2074
2023
|
|
|
2075
|
-
|
|
2024
|
+
color = '#' + color.substring( 2 );
|
|
2076
2025
|
|
|
2077
|
-
|
|
2026
|
+
} else if ( ! color.startsWith( '#' ) ) {
|
|
2078
2027
|
|
|
2079
|
-
|
|
2028
|
+
throw new Error( 'LDrawLoader: Invalid color while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
2080
2029
|
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
break;
|
|
2084
|
-
|
|
2085
|
-
case 'EDGE':
|
|
2086
|
-
edgeColor = lineParser.getToken();
|
|
2087
|
-
|
|
2088
|
-
if ( edgeColor.startsWith( '0x' ) ) {
|
|
2089
|
-
|
|
2090
|
-
edgeColor = '#' + edgeColor.substring( 2 );
|
|
2091
|
-
|
|
2092
|
-
} else if ( ! edgeColor.startsWith( '#' ) ) {
|
|
2093
|
-
|
|
2094
|
-
// Try to see if edge color is a color code
|
|
2095
|
-
edgeMaterial = this.getMaterial( edgeColor );
|
|
2096
|
-
|
|
2097
|
-
if ( ! edgeMaterial ) {
|
|
2098
|
-
|
|
2099
|
-
throw new Error( 'LDrawLoader: Invalid edge color while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
2100
|
-
|
|
2101
|
-
} // Get the edge material for this triangle material
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
edgeMaterial = edgeMaterial.userData.edgeMaterial;
|
|
2105
|
-
|
|
2106
|
-
}
|
|
2107
|
-
|
|
2108
|
-
break;
|
|
2109
|
-
|
|
2110
|
-
case 'ALPHA':
|
|
2111
|
-
alpha = parseInt( lineParser.getToken() );
|
|
2030
|
+
}
|
|
2112
2031
|
|
|
2113
|
-
|
|
2032
|
+
break;
|
|
2033
|
+
case 'EDGE':
|
|
2034
|
+
edgeColor = lineParser.getToken();
|
|
2035
|
+
if ( edgeColor.startsWith( '0x' ) ) {
|
|
2114
2036
|
|
|
2115
|
-
|
|
2037
|
+
edgeColor = '#' + edgeColor.substring( 2 );
|
|
2116
2038
|
|
|
2117
|
-
|
|
2039
|
+
} else if ( ! edgeColor.startsWith( '#' ) ) {
|
|
2118
2040
|
|
|
2119
|
-
|
|
2041
|
+
// Try to see if edge color is a color code
|
|
2042
|
+
edgeMaterial = this.getMaterial( edgeColor );
|
|
2043
|
+
if ( ! edgeMaterial ) {
|
|
2120
2044
|
|
|
2121
|
-
|
|
2045
|
+
throw new Error( 'LDrawLoader: Invalid edge color while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
2122
2046
|
|
|
2123
|
-
|
|
2047
|
+
}
|
|
2124
2048
|
|
|
2125
|
-
|
|
2049
|
+
// Get the edge material for this triangle material
|
|
2050
|
+
edgeMaterial = edgeMaterial.userData.edgeMaterial;
|
|
2126
2051
|
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
case 'LUMINANCE':
|
|
2130
|
-
luminance = parseInt( lineParser.getToken() );
|
|
2052
|
+
}
|
|
2131
2053
|
|
|
2132
|
-
|
|
2054
|
+
break;
|
|
2055
|
+
case 'ALPHA':
|
|
2056
|
+
alpha = parseInt( lineParser.getToken() );
|
|
2057
|
+
if ( isNaN( alpha ) ) {
|
|
2133
2058
|
|
|
2134
|
-
|
|
2059
|
+
throw new Error( 'LDrawLoader: Invalid alpha value in material definition' + lineParser.getLineNumberString() + '.' );
|
|
2135
2060
|
|
|
2136
|
-
|
|
2061
|
+
}
|
|
2137
2062
|
|
|
2138
|
-
|
|
2139
|
-
|
|
2063
|
+
alpha = Math.max( 0, Math.min( 1, alpha / 255 ) );
|
|
2064
|
+
if ( alpha < 1 ) {
|
|
2140
2065
|
|
|
2141
|
-
|
|
2142
|
-
finishType = FINISH_TYPE_CHROME;
|
|
2143
|
-
break;
|
|
2066
|
+
isTransparent = true;
|
|
2144
2067
|
|
|
2145
|
-
|
|
2146
|
-
finishType = FINISH_TYPE_PEARLESCENT;
|
|
2147
|
-
break;
|
|
2068
|
+
}
|
|
2148
2069
|
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2070
|
+
break;
|
|
2071
|
+
case 'LUMINANCE':
|
|
2072
|
+
if ( ! parseLuminance( lineParser.getToken() ) ) {
|
|
2152
2073
|
|
|
2153
|
-
|
|
2154
|
-
finishType = FINISH_TYPE_MATTE_METALLIC;
|
|
2155
|
-
break;
|
|
2074
|
+
throw new Error( 'LDrawLoader: Invalid luminance value in material definition' + LineParser.getLineNumberString() + '.' );
|
|
2156
2075
|
|
|
2157
|
-
|
|
2158
|
-
finishType = FINISH_TYPE_METAL;
|
|
2159
|
-
break;
|
|
2076
|
+
}
|
|
2160
2077
|
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2078
|
+
break;
|
|
2079
|
+
case 'CHROME':
|
|
2080
|
+
finishType = FINISH_TYPE_CHROME;
|
|
2081
|
+
break;
|
|
2082
|
+
case 'PEARLESCENT':
|
|
2083
|
+
finishType = FINISH_TYPE_PEARLESCENT;
|
|
2084
|
+
break;
|
|
2085
|
+
case 'RUBBER':
|
|
2086
|
+
finishType = FINISH_TYPE_RUBBER;
|
|
2087
|
+
break;
|
|
2088
|
+
case 'MATTE_METALLIC':
|
|
2089
|
+
finishType = FINISH_TYPE_MATTE_METALLIC;
|
|
2090
|
+
break;
|
|
2091
|
+
case 'METAL':
|
|
2092
|
+
finishType = FINISH_TYPE_METAL;
|
|
2093
|
+
break;
|
|
2094
|
+
case 'MATERIAL':
|
|
2095
|
+
// Not implemented
|
|
2096
|
+
lineParser.setToEnd();
|
|
2097
|
+
break;
|
|
2098
|
+
default:
|
|
2099
|
+
throw new Error( 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
2165
2100
|
|
|
2166
|
-
|
|
2167
|
-
throw new Error( 'LDrawLoader: Unknown token "' + token + '" while parsing material' + lineParser.getLineNumberString() + '.' );
|
|
2101
|
+
}
|
|
2168
2102
|
|
|
2169
2103
|
}
|
|
2170
2104
|
|
|
2171
2105
|
}
|
|
2172
2106
|
|
|
2173
2107
|
let material = null;
|
|
2174
|
-
|
|
2175
2108
|
switch ( finishType ) {
|
|
2176
2109
|
|
|
2177
2110
|
case FINISH_TYPE_DEFAULT:
|
|
@@ -2181,7 +2114,6 @@
|
|
|
2181
2114
|
metalness: 0
|
|
2182
2115
|
} );
|
|
2183
2116
|
break;
|
|
2184
|
-
|
|
2185
2117
|
case FINISH_TYPE_PEARLESCENT:
|
|
2186
2118
|
// Try to imitate pearlescency by making the surface glossy
|
|
2187
2119
|
material = new THREE.MeshStandardMaterial( {
|
|
@@ -2190,7 +2122,6 @@
|
|
|
2190
2122
|
metalness: 0.25
|
|
2191
2123
|
} );
|
|
2192
2124
|
break;
|
|
2193
|
-
|
|
2194
2125
|
case FINISH_TYPE_CHROME:
|
|
2195
2126
|
// Mirror finish surface
|
|
2196
2127
|
material = new THREE.MeshStandardMaterial( {
|
|
@@ -2199,7 +2130,6 @@
|
|
|
2199
2130
|
metalness: 1
|
|
2200
2131
|
} );
|
|
2201
2132
|
break;
|
|
2202
|
-
|
|
2203
2133
|
case FINISH_TYPE_RUBBER:
|
|
2204
2134
|
// Rubber finish
|
|
2205
2135
|
material = new THREE.MeshStandardMaterial( {
|
|
@@ -2208,7 +2138,6 @@
|
|
|
2208
2138
|
metalness: 0
|
|
2209
2139
|
} );
|
|
2210
2140
|
break;
|
|
2211
|
-
|
|
2212
2141
|
case FINISH_TYPE_MATTE_METALLIC:
|
|
2213
2142
|
// Brushed metal finish
|
|
2214
2143
|
material = new THREE.MeshStandardMaterial( {
|
|
@@ -2217,7 +2146,6 @@
|
|
|
2217
2146
|
metalness: 0.4
|
|
2218
2147
|
} );
|
|
2219
2148
|
break;
|
|
2220
|
-
|
|
2221
2149
|
case FINISH_TYPE_METAL:
|
|
2222
2150
|
// Average metal finish
|
|
2223
2151
|
material = new THREE.MeshStandardMaterial( {
|
|
@@ -2226,7 +2154,6 @@
|
|
|
2226
2154
|
metalness: 0.85
|
|
2227
2155
|
} );
|
|
2228
2156
|
break;
|
|
2229
|
-
|
|
2230
2157
|
default:
|
|
2231
2158
|
// Should not happen
|
|
2232
2159
|
break;
|
|
@@ -2240,7 +2167,6 @@
|
|
|
2240
2167
|
material.color.convertSRGBToLinear();
|
|
2241
2168
|
material.polygonOffset = true;
|
|
2242
2169
|
material.polygonOffsetFactor = 1;
|
|
2243
|
-
|
|
2244
2170
|
if ( luminance !== 0 ) {
|
|
2245
2171
|
|
|
2246
2172
|
material.emissive.set( material.color ).multiplyScalar( luminance );
|
|
@@ -2258,8 +2184,9 @@
|
|
|
2258
2184
|
} );
|
|
2259
2185
|
edgeMaterial.userData.code = code;
|
|
2260
2186
|
edgeMaterial.name = name + ' - Edge';
|
|
2261
|
-
edgeMaterial.color.convertSRGBToLinear();
|
|
2187
|
+
edgeMaterial.color.convertSRGBToLinear();
|
|
2262
2188
|
|
|
2189
|
+
// This is the material used for conditional edges
|
|
2263
2190
|
edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial( {
|
|
2264
2191
|
fog: true,
|
|
2265
2192
|
transparent: isTransparent,
|
|
@@ -2268,6 +2195,8 @@
|
|
|
2268
2195
|
opacity: alpha
|
|
2269
2196
|
} );
|
|
2270
2197
|
edgeMaterial.userData.conditionalEdgeMaterial.color.convertSRGBToLinear();
|
|
2198
|
+
edgeMaterial.userData.conditionalEdgeMaterial.userData.code = code;
|
|
2199
|
+
edgeMaterial.userData.conditionalEdgeMaterial.name = name + ' - Conditional Edge';
|
|
2271
2200
|
|
|
2272
2201
|
}
|
|
2273
2202
|
|
|
@@ -2276,29 +2205,54 @@
|
|
|
2276
2205
|
material.userData.edgeMaterial = edgeMaterial;
|
|
2277
2206
|
this.addMaterial( material );
|
|
2278
2207
|
return material;
|
|
2208
|
+
function parseLuminance( token ) {
|
|
2209
|
+
|
|
2210
|
+
// Returns success
|
|
2211
|
+
|
|
2212
|
+
let lum;
|
|
2213
|
+
if ( token.startsWith( 'LUMINANCE' ) ) {
|
|
2214
|
+
|
|
2215
|
+
lum = parseInt( token.substring( 9 ) );
|
|
2216
|
+
|
|
2217
|
+
} else {
|
|
2218
|
+
|
|
2219
|
+
lum = parseInt( token );
|
|
2220
|
+
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
if ( isNaN( lum ) ) {
|
|
2224
|
+
|
|
2225
|
+
return false;
|
|
2226
|
+
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
luminance = Math.max( 0, Math.min( 1, lum / 255 ) );
|
|
2230
|
+
return true;
|
|
2231
|
+
|
|
2232
|
+
}
|
|
2279
2233
|
|
|
2280
2234
|
}
|
|
2235
|
+
computeBuildingSteps( model ) {
|
|
2281
2236
|
|
|
2282
|
-
|
|
2237
|
+
// Sets userdata.buildingStep number in THREE.Group objects and userData.numBuildingSteps number in the root THREE.Group object.
|
|
2283
2238
|
|
|
2284
|
-
// Sets userdata.constructionStep number in THREE.Group objects and userData.numConstructionSteps number in the root THREE.Group object.
|
|
2285
2239
|
let stepNumber = 0;
|
|
2286
2240
|
model.traverse( c => {
|
|
2287
2241
|
|
|
2288
2242
|
if ( c.isGroup ) {
|
|
2289
2243
|
|
|
2290
|
-
if ( c.userData.
|
|
2244
|
+
if ( c.userData.startingBuildingStep ) {
|
|
2291
2245
|
|
|
2292
2246
|
stepNumber ++;
|
|
2293
2247
|
|
|
2294
2248
|
}
|
|
2295
2249
|
|
|
2296
|
-
c.userData.
|
|
2250
|
+
c.userData.buildingStep = stepNumber;
|
|
2297
2251
|
|
|
2298
2252
|
}
|
|
2299
2253
|
|
|
2300
2254
|
} );
|
|
2301
|
-
model.userData.
|
|
2255
|
+
model.userData.numBuildingSteps = stepNumber + 1;
|
|
2302
2256
|
|
|
2303
2257
|
}
|
|
2304
2258
|
|