@lampdotdev/lamp 0.0.0-stage → 0.36.2-nightly.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +397 -2
- package/Resources/Devices/roku.json +410 -0
- package/Resources/Devices/xbox-one.json +367 -0
- package/Resources/GameKit/NOTICE.md +63 -0
- package/Resources/GameKit/apple/LampPage.swift +1813 -0
- package/Resources/GameKit/apple/LampPlayer.swift +46 -0
- package/Resources/GameKit/apple/LampWebApp.swift +63 -0
- package/Resources/GameKit/apple/LampWebGame.swift +87 -0
- package/Resources/GameKit/apple/Native.swift +12 -0
- package/Resources/GameKit/build.sh +55 -0
- package/Resources/GameKit/lamp_game.h +116 -0
- package/Resources/GameKit/lamp_host.h +19 -0
- package/Resources/GameKit/lamp_kit.cpp +61 -0
- package/Resources/GameKit/lamp_sound.cpp +455 -0
- package/Resources/GameKit/lamp_xbox.cpp +374 -0
- package/Resources/GameKit/libraries/HandmadeMath.h +3940 -0
- package/Resources/GameKit/libraries/cgltf.h +7240 -0
- package/Resources/GameKit/libraries/dr_mp3.h +5430 -0
- package/Resources/GameKit/libraries/dr_wav.h +9209 -0
- package/Resources/GameKit/libraries/sokol_debugtext.h +4754 -0
- package/Resources/GameKit/libraries/sokol_gfx.h +29558 -0
- package/Resources/GameKit/libraries/sokol_gl.h +4538 -0
- package/Resources/GameKit/libraries/sokol_log.h +335 -0
- package/Resources/GameKit/libraries/sokol_shape.h +1531 -0
- package/Resources/GameKit/libraries/stb_image.h +7988 -0
- package/Resources/GameKit/libraries/stb_vorbis.c +5584 -0
- package/Resources/GameKit/page/lamp-live.js +672 -0
- package/Resources/GameKit/scaffold/Game/game.cpp +142 -0
- package/Resources/GameKit/scaffold/Game/scene.glsl +49 -0
- package/Resources/GameKit/scaffold-web/Web/game.js +31 -0
- package/Resources/GameKit/scaffold-web/Web/index.html +13 -0
- package/Resources/GameKit/scaffold-web/Web/making.js +33 -0
- package/Resources/GameKit/scaffold-web/Web/world.js +33 -0
- package/Resources/GameKit/web/lamp-game.js +3042 -0
- package/Resources/GameKit/web/lamp-phaser.js +128 -0
- package/Resources/WebHost/App.exe +0 -0
- package/Resources/WebHost/Microsoft.Web.WebView2.Core.dll +0 -0
- package/Resources/WebHost/WebView2-LICENSE.txt +27 -0
- package/Resources/WebHost/lamp_controllers.h +1506 -0
- package/Resources/WebHost/lamp_web_host.cpp +1173 -0
- package/Resources/WebLibraries/earlier.txt +318 -0
- package/Resources/WebLibraries/phaser/LICENSE.md +20 -0
- package/Resources/WebLibraries/phaser/NOTICE.md +2 -0
- package/Resources/WebLibraries/phaser/phaser.esm.min.js +1 -0
- package/Resources/WebLibraries/qrcode/LICENSE +21 -0
- package/Resources/WebLibraries/qrcode/NOTICE.md +4 -0
- package/Resources/WebLibraries/qrcode/qrcode.js +2297 -0
- package/Resources/WebLibraries/rapier/LICENSE +201 -0
- package/Resources/WebLibraries/rapier/NOTICE.md +3 -0
- package/Resources/WebLibraries/rapier/rapier.js +2 -0
- package/Resources/WebLibraries/three/LICENSE +21 -0
- package/Resources/WebLibraries/three/NOTICE.md +4 -0
- package/Resources/WebLibraries/three/addons/animation/AnimationClipCreator.js +168 -0
- package/Resources/WebLibraries/three/addons/animation/CCDIKSolver.js +607 -0
- package/Resources/WebLibraries/three/addons/controls/ArcballControls.js +3543 -0
- package/Resources/WebLibraries/three/addons/controls/DragControls.js +452 -0
- package/Resources/WebLibraries/three/addons/controls/FirstPersonControls.js +512 -0
- package/Resources/WebLibraries/three/addons/controls/FlyControls.js +384 -0
- package/Resources/WebLibraries/three/addons/controls/MapControls.js +116 -0
- package/Resources/WebLibraries/three/addons/controls/OrbitControls.js +1985 -0
- package/Resources/WebLibraries/three/addons/controls/PointerLockControls.js +264 -0
- package/Resources/WebLibraries/three/addons/controls/TrackballControls.js +1106 -0
- package/Resources/WebLibraries/three/addons/controls/TransformControls.js +2003 -0
- package/Resources/WebLibraries/three/addons/curves/CurveExtras.js +694 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSCurve.js +169 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSSurface.js +98 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSUtils.js +532 -0
- package/Resources/WebLibraries/three/addons/curves/NURBSVolume.js +82 -0
- package/Resources/WebLibraries/three/addons/effects/AnaglyphEffect.js +274 -0
- package/Resources/WebLibraries/three/addons/effects/AsciiEffect.js +323 -0
- package/Resources/WebLibraries/three/addons/effects/OutlineEffect.js +489 -0
- package/Resources/WebLibraries/three/addons/effects/ParallaxBarrierEffect.js +155 -0
- package/Resources/WebLibraries/three/addons/effects/StereoEffect.js +91 -0
- package/Resources/WebLibraries/three/addons/environments/ColorEnvironment.js +59 -0
- package/Resources/WebLibraries/three/addons/environments/DebugEnvironment.js +102 -0
- package/Resources/WebLibraries/three/addons/environments/RoomEnvironment.js +185 -0
- package/Resources/WebLibraries/three/addons/geometries/BoxLineGeometry.js +92 -0
- package/Resources/WebLibraries/three/addons/geometries/ConvexGeometry.js +72 -0
- package/Resources/WebLibraries/three/addons/geometries/DecalGeometry.js +420 -0
- package/Resources/WebLibraries/three/addons/geometries/LoftGeometry.js +355 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricFunctions.js +100 -0
- package/Resources/WebLibraries/three/addons/geometries/ParametricGeometry.js +172 -0
- package/Resources/WebLibraries/three/addons/geometries/RoundedBoxGeometry.js +216 -0
- package/Resources/WebLibraries/three/addons/geometries/TeapotGeometry.js +689 -0
- package/Resources/WebLibraries/three/addons/geometries/TextGeometry.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/AnimationPathHelper.js +302 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelperWebGL.js +221 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelper.js +166 -0
- package/Resources/WebLibraries/three/addons/helpers/LightProbeHelperGPU.js +102 -0
- package/Resources/WebLibraries/three/addons/helpers/OctreeHelper.js +109 -0
- package/Resources/WebLibraries/three/addons/helpers/PositionalAudioHelper.js +169 -0
- package/Resources/WebLibraries/three/addons/helpers/RapierHelper.js +59 -0
- package/Resources/WebLibraries/three/addons/helpers/RectAreaLightHelper.js +118 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelper.js +265 -0
- package/Resources/WebLibraries/three/addons/helpers/TextureHelperGPU.js +214 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexNormalsHelper.js +155 -0
- package/Resources/WebLibraries/three/addons/helpers/VertexTangentsHelper.js +133 -0
- package/Resources/WebLibraries/three/addons/helpers/ViewHelper.js +529 -0
- package/Resources/WebLibraries/three/addons/interactive/HTMLMesh.js +617 -0
- package/Resources/WebLibraries/three/addons/interactive/InteractiveGroup.js +224 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionBox.js +324 -0
- package/Resources/WebLibraries/three/addons/interactive/SelectionHelper.js +150 -0
- package/Resources/WebLibraries/three/addons/libs/fflate.module.js +2699 -0
- package/Resources/WebLibraries/three/addons/libs/lil-gui.module.min.js +8 -0
- package/Resources/WebLibraries/three/addons/libs/meshopt_decoder.module.js +196 -0
- package/Resources/WebLibraries/three/addons/libs/potpack.module.js +125 -0
- package/Resources/WebLibraries/three/addons/libs/stats.module.js +167 -0
- package/Resources/WebLibraries/three/addons/libs/tween.module.js +876 -0
- package/Resources/WebLibraries/three/addons/lighting/ClusteredLighting.js +153 -0
- package/Resources/WebLibraries/three/addons/lighting/DynamicLighting.js +82 -0
- package/Resources/WebLibraries/three/addons/lighting/LightMapper.js +295 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGrid.js +923 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridUtils.js +107 -0
- package/Resources/WebLibraries/three/addons/lighting/LightProbeGridWebGL.js +846 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIConeTracer.js +243 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIIrradiance.js +43 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGINode.js +617 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGISceneCollector.js +793 -0
- package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIVolume.js +1440 -0
- package/Resources/WebLibraries/three/addons/lights/LightProbeGenerator.js +337 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightTexturesLib.js +127 -0
- package/Resources/WebLibraries/three/addons/lights/RectAreaLightUniformsLib.js +40 -0
- package/Resources/WebLibraries/three/addons/lights/SunLight.js +100 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightNode.js +56 -0
- package/Resources/WebLibraries/three/addons/lights/SunLightShadow.js +319 -0
- package/Resources/WebLibraries/three/addons/lights/SunShadowNode.js +312 -0
- package/Resources/WebLibraries/three/addons/lines/Line2.js +56 -0
- package/Resources/WebLibraries/three/addons/lines/LineGeometry.js +157 -0
- package/Resources/WebLibraries/three/addons/lines/LineMaterial.js +742 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegments2.js +434 -0
- package/Resources/WebLibraries/three/addons/lines/LineSegmentsGeometry.js +298 -0
- package/Resources/WebLibraries/three/addons/lines/Wireframe.js +108 -0
- package/Resources/WebLibraries/three/addons/lines/WireframeGeometry2.js +49 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Line2.js +46 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/LineSegments2.js +419 -0
- package/Resources/WebLibraries/three/addons/lines/webgpu/Wireframe.js +86 -0
- package/Resources/WebLibraries/three/addons/loaders/EXRLoader.js +3411 -0
- package/Resources/WebLibraries/three/addons/loaders/FBXLoader.js +4660 -0
- package/Resources/WebLibraries/three/addons/loaders/FontLoader.js +262 -0
- package/Resources/WebLibraries/three/addons/loaders/GLTFLoader.js +5006 -0
- package/Resources/WebLibraries/three/addons/loaders/HDRLoader.js +463 -0
- package/Resources/WebLibraries/three/addons/loaders/MTLLoader.js +601 -0
- package/Resources/WebLibraries/three/addons/loaders/OBJLoader.js +961 -0
- package/Resources/WebLibraries/three/addons/loaders/PLYLoader.js +992 -0
- package/Resources/WebLibraries/three/addons/loaders/RGBELoader.js +18 -0
- package/Resources/WebLibraries/three/addons/loaders/STLLoader.js +423 -0
- package/Resources/WebLibraries/three/addons/loaders/SVGLoader.js +3297 -0
- package/Resources/WebLibraries/three/addons/loaders/TGALoader.js +539 -0
- package/Resources/WebLibraries/three/addons/loaders/UltraHDRLoader.js +757 -0
- package/Resources/WebLibraries/three/addons/math/Capsule.js +159 -0
- package/Resources/WebLibraries/three/addons/math/ColorConverter.js +62 -0
- package/Resources/WebLibraries/three/addons/math/ColorSpaces.js +147 -0
- package/Resources/WebLibraries/three/addons/math/ConvexHull.js +1695 -0
- package/Resources/WebLibraries/three/addons/math/ImprovedNoise.js +88 -0
- package/Resources/WebLibraries/three/addons/math/Lut.js +317 -0
- package/Resources/WebLibraries/three/addons/math/MeshSurfaceSampler.js +315 -0
- package/Resources/WebLibraries/three/addons/math/OBB.js +535 -0
- package/Resources/WebLibraries/three/addons/math/Octree.js +825 -0
- package/Resources/WebLibraries/three/addons/math/SimplexNoise.js +470 -0
- package/Resources/WebLibraries/three/addons/misc/ConvexObjectBreaker.js +539 -0
- package/Resources/WebLibraries/three/addons/misc/GPUComputationRenderer.js +508 -0
- package/Resources/WebLibraries/three/addons/misc/Gyroscope.js +78 -0
- package/Resources/WebLibraries/three/addons/misc/MorphAnimMesh.js +119 -0
- package/Resources/WebLibraries/three/addons/misc/MorphBlendMesh.js +425 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMap.js +370 -0
- package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMapGPU.js +322 -0
- package/Resources/WebLibraries/three/addons/misc/RollerCoaster.js +661 -0
- package/Resources/WebLibraries/three/addons/misc/Sculptor.js +1679 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorMesh.js +1504 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorTools.js +1180 -0
- package/Resources/WebLibraries/three/addons/misc/SculptorUtils.js +345 -0
- package/Resources/WebLibraries/three/addons/misc/TileCreasedNormalsPlugin.js +270 -0
- package/Resources/WebLibraries/three/addons/misc/TubePainter.js +611 -0
- package/Resources/WebLibraries/three/addons/misc/Volume.js +520 -0
- package/Resources/WebLibraries/three/addons/misc/VolumeSlice.js +275 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifier.js +374 -0
- package/Resources/WebLibraries/three/addons/modifiers/CurveModifierGPU.js +256 -0
- package/Resources/WebLibraries/three/addons/modifiers/EdgeSplitModifier.js +299 -0
- package/Resources/WebLibraries/three/addons/modifiers/TessellateModifier.js +340 -0
- package/Resources/WebLibraries/three/addons/objects/GroundedSkybox.js +69 -0
- package/Resources/WebLibraries/three/addons/objects/Lensflare.js +489 -0
- package/Resources/WebLibraries/three/addons/objects/LensflareMesh.js +376 -0
- package/Resources/WebLibraries/three/addons/objects/MarchingCubes.js +1261 -0
- package/Resources/WebLibraries/three/addons/objects/Reflector.js +390 -0
- package/Resources/WebLibraries/three/addons/objects/ReflectorForSSRPass.js +393 -0
- package/Resources/WebLibraries/three/addons/objects/Refractor.js +389 -0
- package/Resources/WebLibraries/three/addons/objects/ShadowMesh.js +130 -0
- package/Resources/WebLibraries/three/addons/objects/Sky.js +342 -0
- package/Resources/WebLibraries/three/addons/objects/SkyMesh.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water.js +374 -0
- package/Resources/WebLibraries/three/addons/objects/Water2.js +403 -0
- package/Resources/WebLibraries/three/addons/objects/Water2Mesh.js +199 -0
- package/Resources/WebLibraries/three/addons/objects/WaterMesh.js +194 -0
- package/Resources/WebLibraries/three/addons/postprocessing/AfterimagePass.js +187 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BloomPass.js +274 -0
- package/Resources/WebLibraries/three/addons/postprocessing/BokehPass.js +218 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ClearPass.js +97 -0
- package/Resources/WebLibraries/three/addons/postprocessing/CubeTexturePass.js +146 -0
- package/Resources/WebLibraries/three/addons/postprocessing/DotScreenPass.js +114 -0
- package/Resources/WebLibraries/three/addons/postprocessing/EffectComposer.js +365 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FXAAPass.js +40 -0
- package/Resources/WebLibraries/three/addons/postprocessing/FilmPass.js +113 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GTAOPass.js +735 -0
- package/Resources/WebLibraries/three/addons/postprocessing/GlitchPass.js +177 -0
- package/Resources/WebLibraries/three/addons/postprocessing/HalftonePass.js +134 -0
- package/Resources/WebLibraries/three/addons/postprocessing/LUTPass.js +138 -0
- package/Resources/WebLibraries/three/addons/postprocessing/MaskPass.js +195 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutlinePass.js +776 -0
- package/Resources/WebLibraries/three/addons/postprocessing/OutputPass.js +148 -0
- package/Resources/WebLibraries/three/addons/postprocessing/Pass.js +191 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPass.js +193 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderPixelatedPass.js +314 -0
- package/Resources/WebLibraries/three/addons/postprocessing/RenderTransitionPass.js +267 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SAOPass.js +407 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SMAAPass.js +230 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAARenderPass.js +313 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSAOPass.js +527 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SSRPass.js +858 -0
- package/Resources/WebLibraries/three/addons/postprocessing/SavePass.js +132 -0
- package/Resources/WebLibraries/three/addons/postprocessing/ShaderPass.js +135 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TAARenderPass.js +243 -0
- package/Resources/WebLibraries/three/addons/postprocessing/TexturePass.js +131 -0
- package/Resources/WebLibraries/three/addons/postprocessing/UnrealBloomPass.js +541 -0
- package/Resources/WebLibraries/three/addons/shaders/ACESFilmicToneMappingShader.js +96 -0
- package/Resources/WebLibraries/three/addons/shaders/AfterimageShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/BasicShader.js +36 -0
- package/Resources/WebLibraries/three/addons/shaders/BleachBypassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/BlendShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader.js +151 -0
- package/Resources/WebLibraries/three/addons/shaders/BokehShader2.js +404 -0
- package/Resources/WebLibraries/three/addons/shaders/BrightnessContrastShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorCorrectionShader.js +59 -0
- package/Resources/WebLibraries/three/addons/shaders/ColorifyShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/ConvolutionShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/CopyShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/DOFMipMapShader.js +63 -0
- package/Resources/WebLibraries/three/addons/shaders/DepthLimitedBlurShader.js +183 -0
- package/Resources/WebLibraries/three/addons/shaders/DigitalGlitch.js +104 -0
- package/Resources/WebLibraries/three/addons/shaders/DotScreenShader.js +75 -0
- package/Resources/WebLibraries/three/addons/shaders/ExposureShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/FXAAShader.js +298 -0
- package/Resources/WebLibraries/three/addons/shaders/FilmShader.js +73 -0
- package/Resources/WebLibraries/three/addons/shaders/FocusShader.js +94 -0
- package/Resources/WebLibraries/three/addons/shaders/FreiChenShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/GTAOShader.js +437 -0
- package/Resources/WebLibraries/three/addons/shaders/GammaCorrectionShader.js +52 -0
- package/Resources/WebLibraries/three/addons/shaders/HalftoneShader.js +332 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalBlurShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/HorizontalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/HueSaturationShader.js +74 -0
- package/Resources/WebLibraries/three/addons/shaders/KaleidoShader.js +65 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityHighPassShader.js +68 -0
- package/Resources/WebLibraries/three/addons/shaders/LuminosityShader.js +54 -0
- package/Resources/WebLibraries/three/addons/shaders/MirrorShader.js +62 -0
- package/Resources/WebLibraries/three/addons/shaders/NormalMapShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/OutputShader.js +103 -0
- package/Resources/WebLibraries/three/addons/shaders/PoissonDenoiseShader.js +230 -0
- package/Resources/WebLibraries/three/addons/shaders/RGBShiftShader.js +61 -0
- package/Resources/WebLibraries/three/addons/shaders/SAOShader.js +201 -0
- package/Resources/WebLibraries/three/addons/shaders/SMAAShader.js +489 -0
- package/Resources/WebLibraries/three/addons/shaders/SSAOShader.js +331 -0
- package/Resources/WebLibraries/three/addons/shaders/SSRShader.js +396 -0
- package/Resources/WebLibraries/three/addons/shaders/SepiaShader.js +57 -0
- package/Resources/WebLibraries/three/addons/shaders/SobelOperatorShader.js +98 -0
- package/Resources/WebLibraries/three/addons/shaders/SubsurfaceScatteringShader.js +95 -0
- package/Resources/WebLibraries/three/addons/shaders/TechnicolorShader.js +51 -0
- package/Resources/WebLibraries/three/addons/shaders/ToonShader.js +349 -0
- package/Resources/WebLibraries/three/addons/shaders/TriangleBlurShader.js +79 -0
- package/Resources/WebLibraries/three/addons/shaders/UnpackDepthRGBAShader.js +60 -0
- package/Resources/WebLibraries/three/addons/shaders/VelocityShader.js +137 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalBlurShader.js +66 -0
- package/Resources/WebLibraries/three/addons/shaders/VerticalTiltShiftShader.js +70 -0
- package/Resources/WebLibraries/three/addons/shaders/VignetteShader.js +56 -0
- package/Resources/WebLibraries/three/addons/shaders/VolumeShader.js +285 -0
- package/Resources/WebLibraries/three/addons/shaders/WaterRefractionShader.js +106 -0
- package/Resources/WebLibraries/three/addons/textures/FlakesTexture.js +54 -0
- package/Resources/WebLibraries/three/addons/tsl/WebGLNodesHandler.js +607 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AfterImageNode.js +256 -0
- package/Resources/WebLibraries/three/addons/tsl/display/AnaglyphPassNode.js +550 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BilateralBlurNode.js +377 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BleachBypass.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/BloomNode.js +599 -0
- package/Resources/WebLibraries/three/addons/tsl/display/CRT.js +150 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ChromaticAberrationNode.js +163 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DenoiseNode.js +354 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DepthOfFieldNode.js +572 -0
- package/Resources/WebLibraries/three/addons/tsl/display/DotScreenNode.js +104 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FSR1Node.js +481 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FXAANode.js +357 -0
- package/Resources/WebLibraries/three/addons/tsl/display/FilmNode.js +101 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GTAONode.js +727 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GaussianBlurNode.js +412 -0
- package/Resources/WebLibraries/three/addons/tsl/display/GodraysNode.js +604 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ImportanceSampledEnvironment.js +564 -0
- package/Resources/WebLibraries/three/addons/tsl/display/LensflareNode.js +282 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Lut3DNode.js +109 -0
- package/Resources/WebLibraries/three/addons/tsl/display/MotionBlur.js +33 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OITPassNode.js +341 -0
- package/Resources/WebLibraries/three/addons/tsl/display/OutlineNode.js +916 -0
- package/Resources/WebLibraries/three/addons/tsl/display/ParallaxBarrierPassNode.js +90 -0
- package/Resources/WebLibraries/three/addons/tsl/display/PixelationPassNode.js +227 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RGBShiftNode.js +96 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RecurrentDenoiseNode.js +812 -0
- package/Resources/WebLibraries/three/addons/tsl/display/RetroPassNode.js +263 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SMAANode.js +729 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAAPassNode.js +344 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSAONode.js +422 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSGINode.js +698 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSRNode.js +1430 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SSSNode.js +479 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Sepia.js +24 -0
- package/Resources/WebLibraries/three/addons/tsl/display/Shape.js +29 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SharpenNode.js +284 -0
- package/Resources/WebLibraries/three/addons/tsl/display/SobelOperatorNode.js +168 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoCompositePassNode.js +190 -0
- package/Resources/WebLibraries/three/addons/tsl/display/StereoPassNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TAAUNode.js +700 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TRAANode.js +609 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TemporalReprojectNode.js +1024 -0
- package/Resources/WebLibraries/three/addons/tsl/display/TransitionNode.js +141 -0
- package/Resources/WebLibraries/three/addons/tsl/display/boxBlur.js +65 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlend.js +80 -0
- package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlur.js +63 -0
- package/Resources/WebLibraries/three/addons/tsl/display/hashBlur.js +55 -0
- package/Resources/WebLibraries/three/addons/tsl/display/lensDirt.js +30 -0
- package/Resources/WebLibraries/three/addons/tsl/display/radialBlur.js +68 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/ClusteredLightsNode.js +994 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/DynamicLightsNode.js +201 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/LightProbeGridNode.js +183 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/AmbientLightDataNode.js +67 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/DirectionalLightDataNode.js +117 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/HemisphereLightDataNode.js +105 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/PointLightDataNode.js +140 -0
- package/Resources/WebLibraries/three/addons/tsl/lighting/data/SpotLightDataNode.js +167 -0
- package/Resources/WebLibraries/three/addons/tsl/math/Bayer.js +84 -0
- package/Resources/WebLibraries/three/addons/tsl/math/curlNoise.js +107 -0
- package/Resources/WebLibraries/three/addons/tsl/math/voronoiNoise.js +112 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNode.js +542 -0
- package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNodeHelper.js +212 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/GroundedSkybox.js +62 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/RNoise.js +51 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/Raymarching.js +70 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SoftParticles.js +53 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/SpecularHelpers.js +302 -0
- package/Resources/WebLibraries/three/addons/tsl/utils/TAAUtils.js +184 -0
- package/Resources/WebLibraries/three/addons/utils/BufferGeometryUtils.js +1523 -0
- package/Resources/WebLibraries/three/addons/utils/CameraUtils.js +82 -0
- package/Resources/WebLibraries/three/addons/utils/ColorUtils.js +76 -0
- package/Resources/WebLibraries/three/addons/utils/GaussianSplatUtils.js +229 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryCompressionUtils.js +547 -0
- package/Resources/WebLibraries/three/addons/utils/GeometryUtils.js +226 -0
- package/Resources/WebLibraries/three/addons/utils/LDrawUtils.js +211 -0
- package/Resources/WebLibraries/three/addons/utils/SceneOptimizer.js +459 -0
- package/Resources/WebLibraries/three/addons/utils/SceneUtils.js +363 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewer.js +244 -0
- package/Resources/WebLibraries/three/addons/utils/ShadowMapViewerGPU.js +233 -0
- package/Resources/WebLibraries/three/addons/utils/SkeletonUtils.js +496 -0
- package/Resources/WebLibraries/three/addons/utils/SortUtils.js +175 -0
- package/Resources/WebLibraries/three/addons/utils/UVsDebug.js +173 -0
- package/Resources/WebLibraries/three/addons/utils/WebGLTextureUtils.js +115 -0
- package/Resources/WebLibraries/three/addons/utils/WebGPUTextureUtils.js +81 -0
- package/Resources/WebLibraries/three/addons/utils/WorkerPool.js +167 -0
- package/Resources/WebLibraries/three/addons/utils/unwrapUVs.js +865 -0
- package/Resources/WebLibraries/three/three.core.js +61162 -0
- package/Resources/WebLibraries/three/three.module.js +19537 -0
- package/Resources/WebLibraries/three/three.tsl.js +41903 -0
- package/Resources/WebLibraries/three/three.webgpu.js +53714 -0
- package/Resources/share-rules.json +64 -0
- package/Resources/skills/2d-game/SKILL.md +305 -0
- package/Resources/skills/3d-game/SKILL.md +274 -0
- package/Resources/skills/accounts/SKILL.md +41 -0
- package/Resources/skills/android-design/SKILL.md +159 -0
- package/Resources/skills/app-ai/SKILL.md +154 -0
- package/Resources/skills/app-intents/SKILL.md +31 -0
- package/Resources/skills/app-kinds/SKILL.md +122 -0
- package/Resources/skills/apple-watch/SKILL.md +43 -0
- package/Resources/skills/assets/SKILL.md +183 -0
- package/Resources/skills/building-blocks/SKILL.md +97 -0
- package/Resources/skills/device-control/SKILL.md +56 -0
- package/Resources/skills/device-integrations/SKILL.md +278 -0
- package/Resources/skills/finder-files/SKILL.md +19 -0
- package/Resources/skills/game/SKILL.md +416 -0
- package/Resources/skills/game-3d/SKILL.md +12 -0
- package/Resources/skills/game-art/SKILL.md +11 -0
- package/Resources/skills/game-feel/SKILL.md +13 -0
- package/Resources/skills/game-levels/SKILL.md +12 -0
- package/Resources/skills/game-live/SKILL.md +12 -0
- package/Resources/skills/game-physics/SKILL.md +13 -0
- package/Resources/skills/game-playtest/SKILL.md +26 -0
- package/Resources/skills/game-ui/SKILL.md +278 -0
- package/Resources/skills/github-projects/SKILL.md +62 -0
- package/Resources/skills/icloud-sync/SKILL.md +30 -0
- package/Resources/skills/iphone-hardware/SKILL.md +57 -0
- package/Resources/skills/iphone-widgets/SKILL.md +53 -0
- package/Resources/skills/lg-developer-mode/SKILL.md +152 -0
- package/Resources/skills/mac-widgets/SKILL.md +60 -0
- package/Resources/skills/maps/SKILL.md +8 -0
- package/Resources/skills/menu-bar/SKILL.md +36 -0
- package/Resources/skills/more-apps/SKILL.md +53 -0
- package/Resources/skills/phone-controllers/SKILL.md +79 -0
- package/Resources/skills/phone-pages/SKILL.md +173 -0
- package/Resources/skills/roku-developer-mode/SKILL.md +106 -0
- package/Resources/skills/scene-3d/SKILL.md +27 -0
- package/Resources/skills/scripting/SKILL.md +17 -0
- package/Resources/skills/share-extension/SKILL.md +22 -0
- package/Resources/skills/tv-design/SKILL.md +72 -0
- package/Resources/skills/web-app/SKILL.md +170 -0
- package/Resources/skills/web-game/SKILL.md +95 -0
- package/Resources/skills/web-or-native/SKILL.md +108 -0
- package/Resources/skills/wish-links/SKILL.md +156 -0
- package/THIRD_PARTY_NOTICES.md +170 -0
- package/cli/ai.mjs +237 -0
- package/cli/android.mjs +941 -0
- package/cli/app-ai.mjs +473 -0
- package/cli/browser.mjs +284 -0
- package/cli/calls.mjs +594 -0
- package/cli/dev.mjs +820 -0
- package/cli/devices.mjs +984 -0
- package/cli/lamp.mjs +1326 -0
- package/cli/lampapp.mjs +332 -0
- package/cli/lamps/android-host/LampPageGateway.kt +345 -0
- package/cli/lamps/android-host/app/build.gradle.kts +40 -0
- package/cli/lamps/android-host/build.gradle.kts +4 -0
- package/cli/lamps/android-host/game/AndroidManifest.xml +33 -0
- package/cli/lamps/android-host/game/MainActivity.kt +173 -0
- package/cli/lamps/android-host/gradle/libs.versions.toml +39 -0
- package/cli/lamps/android-host/gradle.properties +8 -0
- package/cli/lamps/android-host/page/AndroidManifest.xml +35 -0
- package/cli/lamps/android-host/page/MainActivity.kt +193 -0
- package/cli/lamps/android-host/settings.gradle.kts +30 -0
- package/cli/lamps/android-host/tools.json +43 -0
- package/cli/lamps/lamp-controllers.js +2 -0
- package/cli/lamps/lamp-for-games.js +6922 -0
- package/cli/lamps/lamp.js +7082 -0
- package/cli/lamps/mac-starter/.lamp/meta.json +1 -0
- package/cli/lamps/mac-starter/APP.md +12 -0
- package/cli/lamps/mac-starter/Package.swift +8 -0
- package/cli/lamps/mac-starter/Sources/App.swift +11 -0
- package/cli/lamps/mac-starter/Sources/ContentView.swift +17 -0
- package/cli/lamps/mac-starter/Sources/LampSupport.swift +18215 -0
- package/cli/lamps/mac-starter/build.sh +336 -0
- package/cli/lamps/mac-starter/gitignore +3 -0
- package/cli/lamps/mac-starter/lamp-starter.json +6 -0
- package/cli/lamps/web-starter/APP.md +8 -0
- package/cli/lamps/web-starter/app.js +1 -0
- package/cli/lamps/web-starter/index.html +17 -0
- package/cli/lamps/web-starter/lamp-starter.json +5 -0
- package/cli/lamps/web-starter/lamp.js +7082 -0
- package/cli/lamps/web-starter/style.css +25 -0
- package/cli/link.mjs +202 -0
- package/cli/local-ai.mjs +193 -0
- package/cli/mac.mjs +621 -0
- package/cli/mdns.mjs +205 -0
- package/cli/msix.mjs +413 -0
- package/cli/network.mjs +209 -0
- package/cli/openrouter.mjs +133 -0
- package/cli/outside.mjs +203 -0
- package/cli/page.js +317 -0
- package/cli/place.mjs +298 -0
- package/cli/png.mjs +184 -0
- package/cli/share.mjs +270 -0
- package/cli/skill/SKILL.md +280 -0
- package/cli/skills.mjs +71 -0
- package/cli/state.mjs +176 -0
- package/cli/update.mjs +162 -0
- package/package.json +20 -4
- package/site/lib/quota.js +59 -0
- package/site/lib/shared-wishes.js +1727 -0
|
@@ -0,0 +1,3543 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Controls,
|
|
3
|
+
GridHelper,
|
|
4
|
+
EllipseCurve,
|
|
5
|
+
BufferGeometry,
|
|
6
|
+
Line,
|
|
7
|
+
LineBasicMaterial,
|
|
8
|
+
Raycaster,
|
|
9
|
+
Group,
|
|
10
|
+
Box3,
|
|
11
|
+
Sphere,
|
|
12
|
+
Quaternion,
|
|
13
|
+
Vector2,
|
|
14
|
+
Vector3,
|
|
15
|
+
Matrix4,
|
|
16
|
+
MathUtils
|
|
17
|
+
} from 'three';
|
|
18
|
+
|
|
19
|
+
//trackball state
|
|
20
|
+
const STATE = {
|
|
21
|
+
|
|
22
|
+
IDLE: Symbol(),
|
|
23
|
+
ROTATE: Symbol(),
|
|
24
|
+
PAN: Symbol(),
|
|
25
|
+
SCALE: Symbol(),
|
|
26
|
+
FOV: Symbol(),
|
|
27
|
+
FOCUS: Symbol(),
|
|
28
|
+
ZROTATE: Symbol(),
|
|
29
|
+
TOUCH_MULTI: Symbol(),
|
|
30
|
+
ANIMATION_FOCUS: Symbol(),
|
|
31
|
+
ANIMATION_ROTATE: Symbol()
|
|
32
|
+
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const INPUT = {
|
|
36
|
+
|
|
37
|
+
NONE: Symbol(),
|
|
38
|
+
ONE_FINGER: Symbol(),
|
|
39
|
+
ONE_FINGER_SWITCHED: Symbol(),
|
|
40
|
+
TWO_FINGER: Symbol(),
|
|
41
|
+
MULT_FINGER: Symbol(),
|
|
42
|
+
CURSOR: Symbol()
|
|
43
|
+
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
//cursor center coordinates
|
|
47
|
+
const _center = {
|
|
48
|
+
|
|
49
|
+
x: 0,
|
|
50
|
+
y: 0
|
|
51
|
+
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
//transformation matrices for gizmos and camera
|
|
55
|
+
const _transformation = {
|
|
56
|
+
|
|
57
|
+
camera: new Matrix4(),
|
|
58
|
+
gizmos: new Matrix4()
|
|
59
|
+
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Fires when the camera has been transformed by the controls.
|
|
64
|
+
*
|
|
65
|
+
* @event ArcballControls#change
|
|
66
|
+
* @type {Object}
|
|
67
|
+
*/
|
|
68
|
+
const _changeEvent = { type: 'change' };
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Fires when an interaction was initiated.
|
|
72
|
+
*
|
|
73
|
+
* @event ArcballControls#start
|
|
74
|
+
* @type {Object}
|
|
75
|
+
*/
|
|
76
|
+
const _startEvent = { type: 'start' };
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Fires when an interaction has finished.
|
|
80
|
+
*
|
|
81
|
+
* @event ArcballControls#end
|
|
82
|
+
* @type {Object}
|
|
83
|
+
*/
|
|
84
|
+
const _endEvent = { type: 'end' };
|
|
85
|
+
|
|
86
|
+
const _raycaster = new Raycaster();
|
|
87
|
+
const _offset = new Vector3();
|
|
88
|
+
|
|
89
|
+
const _gizmoMatrixStateTemp = new Matrix4();
|
|
90
|
+
const _cameraMatrixStateTemp = new Matrix4();
|
|
91
|
+
const _scalePointTemp = new Vector3();
|
|
92
|
+
|
|
93
|
+
const _EPS = 0.000001;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Arcball controls allow the camera to be controlled by a virtual trackball with full touch support and advanced navigation functionality.
|
|
97
|
+
* Cursor/finger positions and movements are mapped over a virtual trackball surface represented by a gizmo and mapped in intuitive and
|
|
98
|
+
* consistent camera movements. Dragging cursor/fingers will cause camera to orbit around the center of the trackball in a conservative
|
|
99
|
+
* way (returning to the starting point will make the camera return to its starting orientation).
|
|
100
|
+
*
|
|
101
|
+
* In addition to supporting pan, zoom and pinch gestures, double clicking/tapping focuses on a point, intuitively moving the object's
|
|
102
|
+
* point of interest to the center of the virtual trackball. Focus allows a much better inspection and navigation in complex environment.
|
|
103
|
+
* Moreover Arcball controls allow FOV manipulation (in a vertigo-style method) and z-rotation. Saving and restoring of Camera State
|
|
104
|
+
* is supported also through clipboard (use ctrl+c and ctrl+v shortcuts for copy and paste the state).
|
|
105
|
+
*
|
|
106
|
+
* Unlike {@link OrbitControls} and {@link TrackballControls}, `ArcballControls` doesn't require `update()` to be called externally in an
|
|
107
|
+
* animation loop when animations are on.
|
|
108
|
+
*
|
|
109
|
+
* @augments Controls
|
|
110
|
+
* @three_import import { ArcballControls } from 'three/addons/controls/ArcballControls.js';
|
|
111
|
+
*/
|
|
112
|
+
class ArcballControls extends Controls {
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Constructs a new controls instance.
|
|
116
|
+
*
|
|
117
|
+
* @param {Camera} camera - The camera to be controlled. The camera must not be a child of another object, unless that object is the scene itself.
|
|
118
|
+
* @param {?HTMLElement} [domElement=null] - The HTML element used for event listeners.
|
|
119
|
+
* @param {?Scene} [scene=null] The scene rendered by the camera. If not given, gizmos cannot be shown.
|
|
120
|
+
*/
|
|
121
|
+
constructor( camera, domElement = null, scene = null ) {
|
|
122
|
+
|
|
123
|
+
super( camera, domElement );
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The scene rendered by the camera. If not given, gizmos cannot be shown.
|
|
127
|
+
*
|
|
128
|
+
* @type {?Scene}
|
|
129
|
+
* @default null
|
|
130
|
+
*/
|
|
131
|
+
this.scene = scene;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The control's focus point.
|
|
135
|
+
*
|
|
136
|
+
* @type {Vector3}
|
|
137
|
+
*/
|
|
138
|
+
this.target = new Vector3();
|
|
139
|
+
this._currentTarget = new Vector3();
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The size of the gizmo relative to the screen width and height.
|
|
143
|
+
*
|
|
144
|
+
* @type {number}
|
|
145
|
+
* @default 0.67
|
|
146
|
+
*/
|
|
147
|
+
this.radiusFactor = 0.67;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Holds the mouse actions of this controls. This property is maintained by the methods
|
|
151
|
+
* `setMouseAction()` and `unsetMouseAction()`.
|
|
152
|
+
*
|
|
153
|
+
* @type {Array<Object>}
|
|
154
|
+
*/
|
|
155
|
+
this.mouseActions = [];
|
|
156
|
+
this._mouseOp = null;
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
//global vectors and matrices that are used in some operations to avoid creating new objects every time (e.g. every time cursor moves)
|
|
160
|
+
this._v2_1 = new Vector2();
|
|
161
|
+
this._v3_1 = new Vector3();
|
|
162
|
+
this._v3_2 = new Vector3();
|
|
163
|
+
|
|
164
|
+
this._m4_1 = new Matrix4();
|
|
165
|
+
this._m4_2 = new Matrix4();
|
|
166
|
+
|
|
167
|
+
this._quat = new Quaternion();
|
|
168
|
+
|
|
169
|
+
//transformation matrices
|
|
170
|
+
this._translationMatrix = new Matrix4(); //matrix for translation operation
|
|
171
|
+
this._rotationMatrix = new Matrix4(); //matrix for rotation operation
|
|
172
|
+
this._scaleMatrix = new Matrix4(); //matrix for scaling operation
|
|
173
|
+
|
|
174
|
+
this._rotationAxis = new Vector3(); //axis for rotate operation
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
//camera state
|
|
178
|
+
this._cameraMatrixState = new Matrix4();
|
|
179
|
+
this._cameraProjectionState = new Matrix4();
|
|
180
|
+
|
|
181
|
+
this._fovState = 1;
|
|
182
|
+
this._upState = new Vector3();
|
|
183
|
+
this._zoomState = 1;
|
|
184
|
+
this._nearPos = 0;
|
|
185
|
+
this._farPos = 0;
|
|
186
|
+
|
|
187
|
+
this._gizmoMatrixState = new Matrix4();
|
|
188
|
+
|
|
189
|
+
//initial values
|
|
190
|
+
this._up0 = new Vector3();
|
|
191
|
+
this._zoom0 = 1;
|
|
192
|
+
this._fov0 = 0;
|
|
193
|
+
this._initialNear = 0;
|
|
194
|
+
this._nearPos0 = 0;
|
|
195
|
+
this._initialFar = 0;
|
|
196
|
+
this._farPos0 = 0;
|
|
197
|
+
this._cameraMatrixState0 = new Matrix4();
|
|
198
|
+
this._gizmoMatrixState0 = new Matrix4();
|
|
199
|
+
this._target0 = new Vector3();
|
|
200
|
+
|
|
201
|
+
//pointers array
|
|
202
|
+
this._button = - 1;
|
|
203
|
+
this._touchStart = [];
|
|
204
|
+
this._touchCurrent = [];
|
|
205
|
+
this._input = INPUT.NONE;
|
|
206
|
+
|
|
207
|
+
//two fingers touch interaction
|
|
208
|
+
this._switchSensibility = 32; //minimum movement to be performed to fire single pan start after the second finger has been released
|
|
209
|
+
this._startFingerDistance = 0; //distance between two fingers
|
|
210
|
+
this._currentFingerDistance = 0;
|
|
211
|
+
this._startFingerRotation = 0; //amount of rotation performed with two fingers
|
|
212
|
+
this._currentFingerRotation = 0;
|
|
213
|
+
|
|
214
|
+
//double tap
|
|
215
|
+
this._devPxRatio = 0;
|
|
216
|
+
this._downValid = true;
|
|
217
|
+
this._nclicks = 0;
|
|
218
|
+
this._downEvents = [];
|
|
219
|
+
this._downStart = 0; //pointerDown time
|
|
220
|
+
this._clickStart = 0; //first click time
|
|
221
|
+
this._maxDownTime = 250;
|
|
222
|
+
this._maxInterval = 300;
|
|
223
|
+
this._posThreshold = 24;
|
|
224
|
+
this._movementThreshold = 24;
|
|
225
|
+
|
|
226
|
+
//cursor positions
|
|
227
|
+
this._currentCursorPosition = new Vector3();
|
|
228
|
+
this._startCursorPosition = new Vector3();
|
|
229
|
+
|
|
230
|
+
//grid
|
|
231
|
+
this._grid = null; //grid to be visualized during pan operation
|
|
232
|
+
this._gridPosition = new Vector3();
|
|
233
|
+
|
|
234
|
+
//gizmos
|
|
235
|
+
this._gizmos = new Group();
|
|
236
|
+
this._curvePts = 128;
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
//animations
|
|
240
|
+
this._timeStart = - 1; //initial time
|
|
241
|
+
this._animationId = - 1;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Duration of focus animations in ms.
|
|
245
|
+
*
|
|
246
|
+
* @type {number}
|
|
247
|
+
* @default 500
|
|
248
|
+
*/
|
|
249
|
+
this.focusAnimationTime = 500;
|
|
250
|
+
|
|
251
|
+
//rotate animation
|
|
252
|
+
this._timePrev = 0; //time at which previous rotate operation has been detected
|
|
253
|
+
this._timeCurrent = 0; //time at which current rotate operation has been detected
|
|
254
|
+
this._anglePrev = 0; //angle of previous rotation
|
|
255
|
+
this._angleCurrent = 0; //angle of current rotation
|
|
256
|
+
this._cursorPosPrev = new Vector3(); //cursor position when previous rotate operation has been detected
|
|
257
|
+
this._cursorPosCurr = new Vector3();//cursor position when current rotate operation has been detected
|
|
258
|
+
this._wPrev = 0; //angular velocity of the previous rotate operation
|
|
259
|
+
this._wCurr = 0; //angular velocity of the current rotate operation
|
|
260
|
+
|
|
261
|
+
//parameters
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* If set to `true`, the camera's near and far values will be adjusted every time zoom is
|
|
265
|
+
* performed trying to maintain the same visible portion given by initial near and far
|
|
266
|
+
* values. Only works with perspective cameras.
|
|
267
|
+
*
|
|
268
|
+
* This feature only works as expected if the camera's initial state (position, near and far values)
|
|
269
|
+
* is correctly configured before creating the controls. Otherwise {@link ArcballControls#setCamera}
|
|
270
|
+
* must be called by the application.
|
|
271
|
+
*
|
|
272
|
+
* @type {boolean}
|
|
273
|
+
* @default false
|
|
274
|
+
*/
|
|
275
|
+
this.adjustNearFar = false;
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* The scaling factor used when performing zoom operation.
|
|
279
|
+
*
|
|
280
|
+
* @type {number}
|
|
281
|
+
* @default 1.1
|
|
282
|
+
*/
|
|
283
|
+
this.scaleFactor = 1.1;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* The damping inertia used if 'enableAnimations` is set to `true`.
|
|
287
|
+
*
|
|
288
|
+
* @type {number}
|
|
289
|
+
* @default 25
|
|
290
|
+
*/
|
|
291
|
+
this.dampingFactor = 25;
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Maximum angular velocity allowed on rotation animation start.
|
|
295
|
+
*
|
|
296
|
+
* @type {number}
|
|
297
|
+
* @default 20
|
|
298
|
+
*/
|
|
299
|
+
this.wMax = 20;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Set to `true` to enable animations for rotation (damping) and focus operation.
|
|
303
|
+
*
|
|
304
|
+
* @type {boolean}
|
|
305
|
+
* @default true
|
|
306
|
+
*/
|
|
307
|
+
this.enableAnimations = true;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* If set to `true`, a grid will appear when panning operation is being performed
|
|
311
|
+
* (desktop interaction only).
|
|
312
|
+
*
|
|
313
|
+
* @type {boolean}
|
|
314
|
+
* @default false
|
|
315
|
+
*/
|
|
316
|
+
this.enableGrid = false;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Set to `true` to make zoom become cursor centered.
|
|
320
|
+
*
|
|
321
|
+
* @type {boolean}
|
|
322
|
+
* @default false
|
|
323
|
+
*/
|
|
324
|
+
this.cursorZoom = false;
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* The minimum FOV in degrees.
|
|
328
|
+
*
|
|
329
|
+
* @type {number}
|
|
330
|
+
* @default 5
|
|
331
|
+
*/
|
|
332
|
+
this.minFov = 5;
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* The maximum FOV in degrees.
|
|
336
|
+
*
|
|
337
|
+
* @type {number}
|
|
338
|
+
* @default 90
|
|
339
|
+
*/
|
|
340
|
+
this.maxFov = 90;
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Speed of rotation.
|
|
344
|
+
*
|
|
345
|
+
* @type {number}
|
|
346
|
+
* @default 1
|
|
347
|
+
*/
|
|
348
|
+
this.rotateSpeed = 1;
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Enable or disable camera panning.
|
|
352
|
+
*
|
|
353
|
+
* @type {boolean}
|
|
354
|
+
* @default true
|
|
355
|
+
*/
|
|
356
|
+
this.enablePan = true;
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Enable or disable camera rotation.
|
|
360
|
+
*
|
|
361
|
+
* @type {boolean}
|
|
362
|
+
* @default true
|
|
363
|
+
*/
|
|
364
|
+
this.enableRotate = true;
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Enable or disable camera zoom.
|
|
368
|
+
*
|
|
369
|
+
* @type {boolean}
|
|
370
|
+
* @default true
|
|
371
|
+
*/
|
|
372
|
+
this.enableZoom = true;
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Enable or disable gizmos.
|
|
376
|
+
*
|
|
377
|
+
* @type {boolean}
|
|
378
|
+
* @default true
|
|
379
|
+
*/
|
|
380
|
+
this.enableGizmos = true;
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Enable or disable camera focusing on double-tap (or click) operations.
|
|
384
|
+
*
|
|
385
|
+
* @type {boolean}
|
|
386
|
+
* @default true
|
|
387
|
+
*/
|
|
388
|
+
this.enableFocus = true;
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* How far you can dolly in. For perspective cameras only.
|
|
392
|
+
*
|
|
393
|
+
* @type {number}
|
|
394
|
+
* @default 0
|
|
395
|
+
*/
|
|
396
|
+
this.minDistance = 0;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* How far you can dolly out. For perspective cameras only.
|
|
400
|
+
*
|
|
401
|
+
* @type {number}
|
|
402
|
+
* @default Infinity
|
|
403
|
+
*/
|
|
404
|
+
this.maxDistance = Infinity;
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* How far you can zoom in. For orthographic cameras only.
|
|
408
|
+
*
|
|
409
|
+
* @type {number}
|
|
410
|
+
* @default 0
|
|
411
|
+
*/
|
|
412
|
+
this.minZoom = 0;
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* How far you can zoom out. For orthographic cameras only.
|
|
416
|
+
*
|
|
417
|
+
* @type {number}
|
|
418
|
+
* @default Infinity
|
|
419
|
+
*/
|
|
420
|
+
this.maxZoom = Infinity;
|
|
421
|
+
|
|
422
|
+
//trackball parameters
|
|
423
|
+
this._tbRadius = 1;
|
|
424
|
+
|
|
425
|
+
//FSA
|
|
426
|
+
this._state = STATE.IDLE;
|
|
427
|
+
|
|
428
|
+
this.setCamera( camera );
|
|
429
|
+
|
|
430
|
+
if ( this.scene != null ) {
|
|
431
|
+
|
|
432
|
+
this.scene.add( this._gizmos );
|
|
433
|
+
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
this.initializeMouseActions();
|
|
437
|
+
|
|
438
|
+
// event listeners
|
|
439
|
+
|
|
440
|
+
this._onContextMenu = onContextMenu.bind( this );
|
|
441
|
+
this._onWheel = onWheel.bind( this );
|
|
442
|
+
this._onPointerUp = onPointerUp.bind( this );
|
|
443
|
+
this._onPointerMove = onPointerMove.bind( this );
|
|
444
|
+
this._onPointerDown = onPointerDown.bind( this );
|
|
445
|
+
this._onPointerCancel = onPointerCancel.bind( this );
|
|
446
|
+
this._onWindowResize = onWindowResize.bind( this );
|
|
447
|
+
|
|
448
|
+
if ( domElement !== null ) {
|
|
449
|
+
|
|
450
|
+
this.connect( domElement );
|
|
451
|
+
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
connect( element ) {
|
|
457
|
+
|
|
458
|
+
super.connect( element );
|
|
459
|
+
|
|
460
|
+
this._devPxRatio = window.devicePixelRatio;
|
|
461
|
+
|
|
462
|
+
this.domElement.addEventListener( 'contextmenu', this._onContextMenu );
|
|
463
|
+
this.domElement.addEventListener( 'wheel', this._onWheel, { passive: false } );
|
|
464
|
+
this.domElement.addEventListener( 'pointerdown', this._onPointerDown );
|
|
465
|
+
this.domElement.addEventListener( 'pointercancel', this._onPointerCancel );
|
|
466
|
+
|
|
467
|
+
window.addEventListener( 'resize', this._onWindowResize );
|
|
468
|
+
|
|
469
|
+
this.domElement.style.touchAction = 'none'; // Disable touch scroll
|
|
470
|
+
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
disconnect() {
|
|
474
|
+
|
|
475
|
+
this.domElement.removeEventListener( 'pointerdown', this._onPointerDown );
|
|
476
|
+
this.domElement.removeEventListener( 'pointercancel', this._onPointerCancel );
|
|
477
|
+
this.domElement.removeEventListener( 'wheel', this._onWheel );
|
|
478
|
+
this.domElement.removeEventListener( 'contextmenu', this._onContextMenu );
|
|
479
|
+
|
|
480
|
+
window.removeEventListener( 'pointermove', this._onPointerMove );
|
|
481
|
+
window.removeEventListener( 'pointerup', this._onPointerUp );
|
|
482
|
+
|
|
483
|
+
window.removeEventListener( 'resize', this._onWindowResize );
|
|
484
|
+
|
|
485
|
+
this.domElement.style.touchAction = ''; // Restore touch scroll
|
|
486
|
+
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
onSinglePanStart( event, operation ) {
|
|
490
|
+
|
|
491
|
+
if ( this.enabled ) {
|
|
492
|
+
|
|
493
|
+
this.dispatchEvent( _startEvent );
|
|
494
|
+
|
|
495
|
+
this.setCenter( event.clientX, event.clientY );
|
|
496
|
+
|
|
497
|
+
switch ( operation ) {
|
|
498
|
+
|
|
499
|
+
case 'PAN':
|
|
500
|
+
|
|
501
|
+
if ( ! this.enablePan ) {
|
|
502
|
+
|
|
503
|
+
return;
|
|
504
|
+
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if ( this._animationId != - 1 ) {
|
|
508
|
+
|
|
509
|
+
cancelAnimationFrame( this._animationId );
|
|
510
|
+
this._animationId = - 1;
|
|
511
|
+
this._timeStart = - 1;
|
|
512
|
+
|
|
513
|
+
this.activateGizmos( false );
|
|
514
|
+
this.dispatchEvent( _changeEvent );
|
|
515
|
+
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
this.updateTbState( STATE.PAN, true );
|
|
519
|
+
this._startCursorPosition.copy( this.unprojectOnTbPlane( this.object, _center.x, _center.y, this.domElement ) );
|
|
520
|
+
if ( this.enableGrid ) {
|
|
521
|
+
|
|
522
|
+
this.drawGrid();
|
|
523
|
+
this.dispatchEvent( _changeEvent );
|
|
524
|
+
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
break;
|
|
528
|
+
|
|
529
|
+
case 'ROTATE':
|
|
530
|
+
|
|
531
|
+
if ( ! this.enableRotate ) {
|
|
532
|
+
|
|
533
|
+
return;
|
|
534
|
+
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if ( this._animationId != - 1 ) {
|
|
538
|
+
|
|
539
|
+
cancelAnimationFrame( this._animationId );
|
|
540
|
+
this._animationId = - 1;
|
|
541
|
+
this._timeStart = - 1;
|
|
542
|
+
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
this.updateTbState( STATE.ROTATE, true );
|
|
546
|
+
this._startCursorPosition.copy( this.unprojectOnTbSurface( this.object, _center.x, _center.y, this.domElement, this._tbRadius ) );
|
|
547
|
+
this.activateGizmos( true );
|
|
548
|
+
if ( this.enableAnimations ) {
|
|
549
|
+
|
|
550
|
+
this._timePrev = this._timeCurrent = performance.now();
|
|
551
|
+
this._angleCurrent = this._anglePrev = 0;
|
|
552
|
+
this._cursorPosPrev.copy( this._startCursorPosition );
|
|
553
|
+
this._cursorPosCurr.copy( this._cursorPosPrev );
|
|
554
|
+
this._wCurr = 0;
|
|
555
|
+
this._wPrev = this._wCurr;
|
|
556
|
+
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
this.dispatchEvent( _changeEvent );
|
|
560
|
+
break;
|
|
561
|
+
|
|
562
|
+
case 'FOV':
|
|
563
|
+
|
|
564
|
+
if ( ! this.object.isPerspectiveCamera || ! this.enableZoom ) {
|
|
565
|
+
|
|
566
|
+
return;
|
|
567
|
+
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
if ( this._animationId != - 1 ) {
|
|
571
|
+
|
|
572
|
+
cancelAnimationFrame( this._animationId );
|
|
573
|
+
this._animationId = - 1;
|
|
574
|
+
this._timeStart = - 1;
|
|
575
|
+
|
|
576
|
+
this.activateGizmos( false );
|
|
577
|
+
this.dispatchEvent( _changeEvent );
|
|
578
|
+
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
this.updateTbState( STATE.FOV, true );
|
|
582
|
+
this._startCursorPosition.setY( this.getCursorNDC( _center.x, _center.y, this.domElement ).y * 0.5 );
|
|
583
|
+
this._currentCursorPosition.copy( this._startCursorPosition );
|
|
584
|
+
break;
|
|
585
|
+
|
|
586
|
+
case 'ZOOM':
|
|
587
|
+
|
|
588
|
+
if ( ! this.enableZoom ) {
|
|
589
|
+
|
|
590
|
+
return;
|
|
591
|
+
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
if ( this._animationId != - 1 ) {
|
|
595
|
+
|
|
596
|
+
cancelAnimationFrame( this._animationId );
|
|
597
|
+
this._animationId = - 1;
|
|
598
|
+
this._timeStart = - 1;
|
|
599
|
+
|
|
600
|
+
this.activateGizmos( false );
|
|
601
|
+
this.dispatchEvent( _changeEvent );
|
|
602
|
+
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
this.updateTbState( STATE.SCALE, true );
|
|
606
|
+
this._startCursorPosition.setY( this.getCursorNDC( _center.x, _center.y, this.domElement ).y * 0.5 );
|
|
607
|
+
this._currentCursorPosition.copy( this._startCursorPosition );
|
|
608
|
+
break;
|
|
609
|
+
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
onSinglePanMove( event, opState ) {
|
|
617
|
+
|
|
618
|
+
if ( this.enabled ) {
|
|
619
|
+
|
|
620
|
+
const restart = opState != this._state;
|
|
621
|
+
this.setCenter( event.clientX, event.clientY );
|
|
622
|
+
|
|
623
|
+
switch ( opState ) {
|
|
624
|
+
|
|
625
|
+
case STATE.PAN:
|
|
626
|
+
|
|
627
|
+
if ( this.enablePan ) {
|
|
628
|
+
|
|
629
|
+
if ( restart ) {
|
|
630
|
+
|
|
631
|
+
//switch to pan operation
|
|
632
|
+
|
|
633
|
+
this.dispatchEvent( _endEvent );
|
|
634
|
+
this.dispatchEvent( _startEvent );
|
|
635
|
+
|
|
636
|
+
this.updateTbState( opState, true );
|
|
637
|
+
this._startCursorPosition.copy( this.unprojectOnTbPlane( this.object, _center.x, _center.y, this.domElement ) );
|
|
638
|
+
if ( this.enableGrid ) {
|
|
639
|
+
|
|
640
|
+
this.drawGrid();
|
|
641
|
+
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
this.activateGizmos( false );
|
|
645
|
+
|
|
646
|
+
} else {
|
|
647
|
+
|
|
648
|
+
//continue with pan operation
|
|
649
|
+
this._currentCursorPosition.copy( this.unprojectOnTbPlane( this.object, _center.x, _center.y, this.domElement ) );
|
|
650
|
+
this.applyTransformMatrix( this.pan( this._startCursorPosition, this._currentCursorPosition ) );
|
|
651
|
+
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
break;
|
|
657
|
+
|
|
658
|
+
case STATE.ROTATE:
|
|
659
|
+
|
|
660
|
+
if ( this.enableRotate ) {
|
|
661
|
+
|
|
662
|
+
if ( restart ) {
|
|
663
|
+
|
|
664
|
+
//switch to rotate operation
|
|
665
|
+
|
|
666
|
+
this.dispatchEvent( _endEvent );
|
|
667
|
+
this.dispatchEvent( _startEvent );
|
|
668
|
+
|
|
669
|
+
this.updateTbState( opState, true );
|
|
670
|
+
this._startCursorPosition.copy( this.unprojectOnTbSurface( this.object, _center.x, _center.y, this.domElement, this._tbRadius ) );
|
|
671
|
+
|
|
672
|
+
if ( this.enableGrid ) {
|
|
673
|
+
|
|
674
|
+
this.disposeGrid();
|
|
675
|
+
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
this.activateGizmos( true );
|
|
679
|
+
|
|
680
|
+
} else {
|
|
681
|
+
|
|
682
|
+
//continue with rotate operation
|
|
683
|
+
this._currentCursorPosition.copy( this.unprojectOnTbSurface( this.object, _center.x, _center.y, this.domElement, this._tbRadius ) );
|
|
684
|
+
|
|
685
|
+
const distance = this._startCursorPosition.distanceTo( this._currentCursorPosition );
|
|
686
|
+
const angle = this._startCursorPosition.angleTo( this._currentCursorPosition );
|
|
687
|
+
const amount = Math.max( distance / this._tbRadius, angle ) * this.rotateSpeed; //effective rotation angle
|
|
688
|
+
|
|
689
|
+
this.applyTransformMatrix( this.rotate( this.calculateRotationAxis( this._startCursorPosition, this._currentCursorPosition ), amount ) );
|
|
690
|
+
|
|
691
|
+
if ( this.enableAnimations ) {
|
|
692
|
+
|
|
693
|
+
this._timePrev = this._timeCurrent;
|
|
694
|
+
this._timeCurrent = performance.now();
|
|
695
|
+
this._anglePrev = this._angleCurrent;
|
|
696
|
+
this._angleCurrent = amount;
|
|
697
|
+
this._cursorPosPrev.copy( this._cursorPosCurr );
|
|
698
|
+
this._cursorPosCurr.copy( this._currentCursorPosition );
|
|
699
|
+
this._wPrev = this._wCurr;
|
|
700
|
+
this._wCurr = this.calculateAngularSpeed( this._anglePrev, this._angleCurrent, this._timePrev, this._timeCurrent );
|
|
701
|
+
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
break;
|
|
709
|
+
|
|
710
|
+
case STATE.SCALE:
|
|
711
|
+
|
|
712
|
+
if ( this.enableZoom ) {
|
|
713
|
+
|
|
714
|
+
if ( restart ) {
|
|
715
|
+
|
|
716
|
+
//switch to zoom operation
|
|
717
|
+
|
|
718
|
+
this.dispatchEvent( _endEvent );
|
|
719
|
+
this.dispatchEvent( _startEvent );
|
|
720
|
+
|
|
721
|
+
this.updateTbState( opState, true );
|
|
722
|
+
this._startCursorPosition.setY( this.getCursorNDC( _center.x, _center.y, this.domElement ).y * 0.5 );
|
|
723
|
+
this._currentCursorPosition.copy( this._startCursorPosition );
|
|
724
|
+
|
|
725
|
+
if ( this.enableGrid ) {
|
|
726
|
+
|
|
727
|
+
this.disposeGrid();
|
|
728
|
+
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
this.activateGizmos( false );
|
|
732
|
+
|
|
733
|
+
} else {
|
|
734
|
+
|
|
735
|
+
//continue with zoom operation
|
|
736
|
+
const screenNotches = 8; //how many wheel notches corresponds to a full screen pan
|
|
737
|
+
this._currentCursorPosition.setY( this.getCursorNDC( _center.x, _center.y, this.domElement ).y * 0.5 );
|
|
738
|
+
|
|
739
|
+
const movement = this._currentCursorPosition.y - this._startCursorPosition.y;
|
|
740
|
+
|
|
741
|
+
let size = 1;
|
|
742
|
+
|
|
743
|
+
if ( movement < 0 ) {
|
|
744
|
+
|
|
745
|
+
size = 1 / ( Math.pow( this.scaleFactor, - movement * screenNotches ) );
|
|
746
|
+
|
|
747
|
+
} else if ( movement > 0 ) {
|
|
748
|
+
|
|
749
|
+
size = Math.pow( this.scaleFactor, movement * screenNotches );
|
|
750
|
+
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
this._v3_1.setFromMatrixPosition( this._gizmoMatrixState );
|
|
754
|
+
|
|
755
|
+
this.applyTransformMatrix( this.scale( size, this._v3_1 ) );
|
|
756
|
+
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
break;
|
|
762
|
+
|
|
763
|
+
case STATE.FOV:
|
|
764
|
+
|
|
765
|
+
if ( this.enableZoom && this.object.isPerspectiveCamera ) {
|
|
766
|
+
|
|
767
|
+
if ( restart ) {
|
|
768
|
+
|
|
769
|
+
//switch to fov operation
|
|
770
|
+
|
|
771
|
+
this.dispatchEvent( _endEvent );
|
|
772
|
+
this.dispatchEvent( _startEvent );
|
|
773
|
+
|
|
774
|
+
this.updateTbState( opState, true );
|
|
775
|
+
this._startCursorPosition.setY( this.getCursorNDC( _center.x, _center.y, this.domElement ).y * 0.5 );
|
|
776
|
+
this._currentCursorPosition.copy( this._startCursorPosition );
|
|
777
|
+
|
|
778
|
+
if ( this.enableGrid ) {
|
|
779
|
+
|
|
780
|
+
this.disposeGrid();
|
|
781
|
+
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
this.activateGizmos( false );
|
|
785
|
+
|
|
786
|
+
} else {
|
|
787
|
+
|
|
788
|
+
//continue with fov operation
|
|
789
|
+
const screenNotches = 8; //how many wheel notches corresponds to a full screen pan
|
|
790
|
+
this._currentCursorPosition.setY( this.getCursorNDC( _center.x, _center.y, this.domElement ).y * 0.5 );
|
|
791
|
+
|
|
792
|
+
const movement = this._currentCursorPosition.y - this._startCursorPosition.y;
|
|
793
|
+
|
|
794
|
+
let size = 1;
|
|
795
|
+
|
|
796
|
+
if ( movement < 0 ) {
|
|
797
|
+
|
|
798
|
+
size = 1 / ( Math.pow( this.scaleFactor, - movement * screenNotches ) );
|
|
799
|
+
|
|
800
|
+
} else if ( movement > 0 ) {
|
|
801
|
+
|
|
802
|
+
size = Math.pow( this.scaleFactor, movement * screenNotches );
|
|
803
|
+
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
this._v3_1.setFromMatrixPosition( this._cameraMatrixState );
|
|
807
|
+
const x = this._v3_1.distanceTo( this._gizmos.position );
|
|
808
|
+
let xNew = x / size; //distance between camera and gizmos if scale(size, scalepoint) would be performed
|
|
809
|
+
|
|
810
|
+
//check min and max distance
|
|
811
|
+
xNew = MathUtils.clamp( xNew, this.minDistance, this.maxDistance );
|
|
812
|
+
|
|
813
|
+
const y = x * Math.tan( MathUtils.DEG2RAD * this._fovState * 0.5 );
|
|
814
|
+
|
|
815
|
+
//calculate new fov
|
|
816
|
+
let newFov = MathUtils.RAD2DEG * ( Math.atan( y / xNew ) * 2 );
|
|
817
|
+
|
|
818
|
+
//check min and max fov
|
|
819
|
+
newFov = MathUtils.clamp( newFov, this.minFov, this.maxFov );
|
|
820
|
+
|
|
821
|
+
const newDistance = y / Math.tan( MathUtils.DEG2RAD * ( newFov / 2 ) );
|
|
822
|
+
size = x / newDistance;
|
|
823
|
+
this._v3_2.setFromMatrixPosition( this._gizmoMatrixState );
|
|
824
|
+
|
|
825
|
+
this.setFov( newFov );
|
|
826
|
+
this.applyTransformMatrix( this.scale( size, this._v3_2, false ) );
|
|
827
|
+
|
|
828
|
+
//adjusting distance
|
|
829
|
+
_offset.copy( this._gizmos.position ).sub( this.object.position ).normalize().multiplyScalar( newDistance / x );
|
|
830
|
+
this._m4_1.makeTranslation( _offset.x, _offset.y, _offset.z );
|
|
831
|
+
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
break;
|
|
837
|
+
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
this.dispatchEvent( _changeEvent );
|
|
841
|
+
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
onSinglePanEnd() {
|
|
847
|
+
|
|
848
|
+
if ( this._state == STATE.ROTATE ) {
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
if ( ! this.enableRotate ) {
|
|
852
|
+
|
|
853
|
+
return;
|
|
854
|
+
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
if ( this.enableAnimations ) {
|
|
858
|
+
|
|
859
|
+
//perform rotation animation
|
|
860
|
+
const deltaTime = ( performance.now() - this._timeCurrent );
|
|
861
|
+
if ( deltaTime < 120 ) {
|
|
862
|
+
|
|
863
|
+
const w = Math.abs( ( this._wPrev + this._wCurr ) / 2 );
|
|
864
|
+
|
|
865
|
+
const self = this;
|
|
866
|
+
this._animationId = window.requestAnimationFrame( function ( t ) {
|
|
867
|
+
|
|
868
|
+
self.updateTbState( STATE.ANIMATION_ROTATE, true );
|
|
869
|
+
const rotationAxis = self.calculateRotationAxis( self._cursorPosPrev, self._cursorPosCurr );
|
|
870
|
+
|
|
871
|
+
self.onRotationAnim( t, rotationAxis, Math.min( w, self.wMax ) );
|
|
872
|
+
|
|
873
|
+
} );
|
|
874
|
+
|
|
875
|
+
} else {
|
|
876
|
+
|
|
877
|
+
//cursor has been standing still for over 120 ms since last movement
|
|
878
|
+
this.updateTbState( STATE.IDLE, false );
|
|
879
|
+
this.activateGizmos( false );
|
|
880
|
+
this.dispatchEvent( _changeEvent );
|
|
881
|
+
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
} else {
|
|
885
|
+
|
|
886
|
+
this.updateTbState( STATE.IDLE, false );
|
|
887
|
+
this.activateGizmos( false );
|
|
888
|
+
this.dispatchEvent( _changeEvent );
|
|
889
|
+
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
} else if ( this._state == STATE.PAN || this._state == STATE.IDLE ) {
|
|
893
|
+
|
|
894
|
+
this.updateTbState( STATE.IDLE, false );
|
|
895
|
+
|
|
896
|
+
if ( this.enableGrid ) {
|
|
897
|
+
|
|
898
|
+
this.disposeGrid();
|
|
899
|
+
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
this.activateGizmos( false );
|
|
903
|
+
this.dispatchEvent( _changeEvent );
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
this.dispatchEvent( _endEvent );
|
|
909
|
+
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
onDoubleTap( event ) {
|
|
913
|
+
|
|
914
|
+
if ( this.enabled && this.enablePan && this.enableFocus && this.scene != null ) {
|
|
915
|
+
|
|
916
|
+
this.dispatchEvent( _startEvent );
|
|
917
|
+
|
|
918
|
+
this.setCenter( event.clientX, event.clientY );
|
|
919
|
+
const hitP = this.unprojectOnObj( this.getCursorNDC( _center.x, _center.y, this.domElement ), this.object );
|
|
920
|
+
|
|
921
|
+
if ( hitP != null && this.enableAnimations ) {
|
|
922
|
+
|
|
923
|
+
const self = this;
|
|
924
|
+
if ( this._animationId != - 1 ) {
|
|
925
|
+
|
|
926
|
+
window.cancelAnimationFrame( this._animationId );
|
|
927
|
+
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
this._timeStart = - 1;
|
|
931
|
+
this._animationId = window.requestAnimationFrame( function ( t ) {
|
|
932
|
+
|
|
933
|
+
self.updateTbState( STATE.ANIMATION_FOCUS, true );
|
|
934
|
+
self.onFocusAnim( t, hitP, self._cameraMatrixState, self._gizmoMatrixState );
|
|
935
|
+
|
|
936
|
+
} );
|
|
937
|
+
|
|
938
|
+
} else if ( hitP != null && ! this.enableAnimations ) {
|
|
939
|
+
|
|
940
|
+
this.updateTbState( STATE.FOCUS, true );
|
|
941
|
+
this.focus( hitP, this.scaleFactor );
|
|
942
|
+
this.updateTbState( STATE.IDLE, false );
|
|
943
|
+
this.dispatchEvent( _changeEvent );
|
|
944
|
+
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
this.dispatchEvent( _endEvent );
|
|
950
|
+
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
onDoublePanStart() {
|
|
954
|
+
|
|
955
|
+
if ( this.enabled && this.enablePan ) {
|
|
956
|
+
|
|
957
|
+
this.dispatchEvent( _startEvent );
|
|
958
|
+
|
|
959
|
+
this.updateTbState( STATE.PAN, true );
|
|
960
|
+
|
|
961
|
+
this.setCenter( ( this._touchCurrent[ 0 ].clientX + this._touchCurrent[ 1 ].clientX ) / 2, ( this._touchCurrent[ 0 ].clientY + this._touchCurrent[ 1 ].clientY ) / 2 );
|
|
962
|
+
this._startCursorPosition.copy( this.unprojectOnTbPlane( this.object, _center.x, _center.y, this.domElement, true ) );
|
|
963
|
+
this._currentCursorPosition.copy( this._startCursorPosition );
|
|
964
|
+
|
|
965
|
+
this.activateGizmos( false );
|
|
966
|
+
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
onDoublePanMove() {
|
|
972
|
+
|
|
973
|
+
if ( this.enabled && this.enablePan ) {
|
|
974
|
+
|
|
975
|
+
this.setCenter( ( this._touchCurrent[ 0 ].clientX + this._touchCurrent[ 1 ].clientX ) / 2, ( this._touchCurrent[ 0 ].clientY + this._touchCurrent[ 1 ].clientY ) / 2 );
|
|
976
|
+
|
|
977
|
+
if ( this._state != STATE.PAN ) {
|
|
978
|
+
|
|
979
|
+
this.updateTbState( STATE.PAN, true );
|
|
980
|
+
this._startCursorPosition.copy( this._currentCursorPosition );
|
|
981
|
+
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
this._currentCursorPosition.copy( this.unprojectOnTbPlane( this.object, _center.x, _center.y, this.domElement, true ) );
|
|
985
|
+
this.applyTransformMatrix( this.pan( this._startCursorPosition, this._currentCursorPosition, true ) );
|
|
986
|
+
this.dispatchEvent( _changeEvent );
|
|
987
|
+
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
onDoublePanEnd() {
|
|
993
|
+
|
|
994
|
+
this.updateTbState( STATE.IDLE, false );
|
|
995
|
+
this.dispatchEvent( _endEvent );
|
|
996
|
+
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
onRotateStart() {
|
|
1000
|
+
|
|
1001
|
+
if ( this.enabled && this.enableRotate ) {
|
|
1002
|
+
|
|
1003
|
+
this.dispatchEvent( _startEvent );
|
|
1004
|
+
|
|
1005
|
+
this.updateTbState( STATE.ZROTATE, true );
|
|
1006
|
+
|
|
1007
|
+
//this._startFingerRotation = event.rotation;
|
|
1008
|
+
|
|
1009
|
+
this._startFingerRotation = this.getAngle( this._touchCurrent[ 1 ], this._touchCurrent[ 0 ] ) + this.getAngle( this._touchStart[ 1 ], this._touchStart[ 0 ] );
|
|
1010
|
+
this._currentFingerRotation = this._startFingerRotation;
|
|
1011
|
+
|
|
1012
|
+
this.object.getWorldDirection( this._rotationAxis ); //rotation axis
|
|
1013
|
+
|
|
1014
|
+
if ( ! this.enablePan && ! this.enableZoom ) {
|
|
1015
|
+
|
|
1016
|
+
this.activateGizmos( true );
|
|
1017
|
+
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
onRotateMove() {
|
|
1025
|
+
|
|
1026
|
+
if ( this.enabled && this.enableRotate ) {
|
|
1027
|
+
|
|
1028
|
+
this.setCenter( ( this._touchCurrent[ 0 ].clientX + this._touchCurrent[ 1 ].clientX ) / 2, ( this._touchCurrent[ 0 ].clientY + this._touchCurrent[ 1 ].clientY ) / 2 );
|
|
1029
|
+
let rotationPoint;
|
|
1030
|
+
|
|
1031
|
+
if ( this._state != STATE.ZROTATE ) {
|
|
1032
|
+
|
|
1033
|
+
this.updateTbState( STATE.ZROTATE, true );
|
|
1034
|
+
this._startFingerRotation = this._currentFingerRotation;
|
|
1035
|
+
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
//this._currentFingerRotation = event.rotation;
|
|
1039
|
+
this._currentFingerRotation = this.getAngle( this._touchCurrent[ 1 ], this._touchCurrent[ 0 ] ) + this.getAngle( this._touchStart[ 1 ], this._touchStart[ 0 ] );
|
|
1040
|
+
|
|
1041
|
+
if ( ! this.enablePan ) {
|
|
1042
|
+
|
|
1043
|
+
rotationPoint = new Vector3().setFromMatrixPosition( this._gizmoMatrixState );
|
|
1044
|
+
|
|
1045
|
+
} else {
|
|
1046
|
+
|
|
1047
|
+
this._v3_2.setFromMatrixPosition( this._gizmoMatrixState );
|
|
1048
|
+
rotationPoint = this.unprojectOnTbPlane( this.object, _center.x, _center.y, this.domElement ).applyQuaternion( this.object.quaternion ).multiplyScalar( 1 / this.object.zoom ).add( this._v3_2 );
|
|
1049
|
+
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
const amount = MathUtils.DEG2RAD * ( this._startFingerRotation - this._currentFingerRotation );
|
|
1053
|
+
|
|
1054
|
+
this.applyTransformMatrix( this.zRotate( rotationPoint, amount ) );
|
|
1055
|
+
this.dispatchEvent( _changeEvent );
|
|
1056
|
+
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
onRotateEnd() {
|
|
1062
|
+
|
|
1063
|
+
this.updateTbState( STATE.IDLE, false );
|
|
1064
|
+
this.activateGizmos( false );
|
|
1065
|
+
this.dispatchEvent( _endEvent );
|
|
1066
|
+
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
onPinchStart() {
|
|
1070
|
+
|
|
1071
|
+
if ( this.enabled && this.enableZoom ) {
|
|
1072
|
+
|
|
1073
|
+
this.dispatchEvent( _startEvent );
|
|
1074
|
+
this.updateTbState( STATE.SCALE, true );
|
|
1075
|
+
|
|
1076
|
+
this._startFingerDistance = this.calculatePointersDistance( this._touchCurrent[ 0 ], this._touchCurrent[ 1 ] );
|
|
1077
|
+
this._currentFingerDistance = this._startFingerDistance;
|
|
1078
|
+
|
|
1079
|
+
this.activateGizmos( false );
|
|
1080
|
+
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
onPinchMove() {
|
|
1086
|
+
|
|
1087
|
+
if ( this.enabled && this.enableZoom ) {
|
|
1088
|
+
|
|
1089
|
+
this.setCenter( ( this._touchCurrent[ 0 ].clientX + this._touchCurrent[ 1 ].clientX ) / 2, ( this._touchCurrent[ 0 ].clientY + this._touchCurrent[ 1 ].clientY ) / 2 );
|
|
1090
|
+
const minDistance = 12; //minimum distance between fingers (in css pixels)
|
|
1091
|
+
|
|
1092
|
+
if ( this._state != STATE.SCALE ) {
|
|
1093
|
+
|
|
1094
|
+
this._startFingerDistance = this._currentFingerDistance;
|
|
1095
|
+
this.updateTbState( STATE.SCALE, true );
|
|
1096
|
+
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
this._currentFingerDistance = Math.max( this.calculatePointersDistance( this._touchCurrent[ 0 ], this._touchCurrent[ 1 ] ), minDistance * this._devPxRatio );
|
|
1100
|
+
const amount = this._currentFingerDistance / this._startFingerDistance;
|
|
1101
|
+
|
|
1102
|
+
let scalePoint;
|
|
1103
|
+
|
|
1104
|
+
if ( ! this.enablePan ) {
|
|
1105
|
+
|
|
1106
|
+
scalePoint = this._gizmos.position;
|
|
1107
|
+
|
|
1108
|
+
} else {
|
|
1109
|
+
|
|
1110
|
+
if ( this.object.isOrthographicCamera ) {
|
|
1111
|
+
|
|
1112
|
+
scalePoint = this.unprojectOnTbPlane( this.object, _center.x, _center.y, this.domElement )
|
|
1113
|
+
.applyQuaternion( this.object.quaternion )
|
|
1114
|
+
.multiplyScalar( 1 / this.object.zoom )
|
|
1115
|
+
.add( this._gizmos.position );
|
|
1116
|
+
|
|
1117
|
+
} else if ( this.object.isPerspectiveCamera ) {
|
|
1118
|
+
|
|
1119
|
+
scalePoint = this.unprojectOnTbPlane( this.object, _center.x, _center.y, this.domElement )
|
|
1120
|
+
.applyQuaternion( this.object.quaternion )
|
|
1121
|
+
.add( this._gizmos.position );
|
|
1122
|
+
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
this.applyTransformMatrix( this.scale( amount, scalePoint ) );
|
|
1128
|
+
this.dispatchEvent( _changeEvent );
|
|
1129
|
+
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
onPinchEnd() {
|
|
1135
|
+
|
|
1136
|
+
this.updateTbState( STATE.IDLE, false );
|
|
1137
|
+
this.dispatchEvent( _endEvent );
|
|
1138
|
+
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
onTriplePanStart() {
|
|
1142
|
+
|
|
1143
|
+
if ( this.enabled && this.enableZoom ) {
|
|
1144
|
+
|
|
1145
|
+
this.dispatchEvent( _startEvent );
|
|
1146
|
+
|
|
1147
|
+
this.updateTbState( STATE.SCALE, true );
|
|
1148
|
+
|
|
1149
|
+
//const center = event.center;
|
|
1150
|
+
let clientX = 0;
|
|
1151
|
+
let clientY = 0;
|
|
1152
|
+
const nFingers = this._touchCurrent.length;
|
|
1153
|
+
|
|
1154
|
+
for ( let i = 0; i < nFingers; i ++ ) {
|
|
1155
|
+
|
|
1156
|
+
clientX += this._touchCurrent[ i ].clientX;
|
|
1157
|
+
clientY += this._touchCurrent[ i ].clientY;
|
|
1158
|
+
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
this.setCenter( clientX / nFingers, clientY / nFingers );
|
|
1162
|
+
|
|
1163
|
+
this._startCursorPosition.setY( this.getCursorNDC( _center.x, _center.y, this.domElement ).y * 0.5 );
|
|
1164
|
+
this._currentCursorPosition.copy( this._startCursorPosition );
|
|
1165
|
+
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
onTriplePanMove() {
|
|
1171
|
+
|
|
1172
|
+
if ( this.enabled && this.enableZoom ) {
|
|
1173
|
+
|
|
1174
|
+
// fov / 2
|
|
1175
|
+
// |\
|
|
1176
|
+
// | \
|
|
1177
|
+
// | \
|
|
1178
|
+
// x | \
|
|
1179
|
+
// | \
|
|
1180
|
+
// | \
|
|
1181
|
+
// | _ _ _\
|
|
1182
|
+
// y
|
|
1183
|
+
|
|
1184
|
+
//const center = event.center;
|
|
1185
|
+
let clientX = 0;
|
|
1186
|
+
let clientY = 0;
|
|
1187
|
+
const nFingers = this._touchCurrent.length;
|
|
1188
|
+
|
|
1189
|
+
for ( let i = 0; i < nFingers; i ++ ) {
|
|
1190
|
+
|
|
1191
|
+
clientX += this._touchCurrent[ i ].clientX;
|
|
1192
|
+
clientY += this._touchCurrent[ i ].clientY;
|
|
1193
|
+
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
this.setCenter( clientX / nFingers, clientY / nFingers );
|
|
1197
|
+
|
|
1198
|
+
const screenNotches = 8; //how many wheel notches corresponds to a full screen pan
|
|
1199
|
+
this._currentCursorPosition.setY( this.getCursorNDC( _center.x, _center.y, this.domElement ).y * 0.5 );
|
|
1200
|
+
|
|
1201
|
+
const movement = this._currentCursorPosition.y - this._startCursorPosition.y;
|
|
1202
|
+
|
|
1203
|
+
let size = 1;
|
|
1204
|
+
|
|
1205
|
+
if ( movement < 0 ) {
|
|
1206
|
+
|
|
1207
|
+
size = 1 / ( Math.pow( this.scaleFactor, - movement * screenNotches ) );
|
|
1208
|
+
|
|
1209
|
+
} else if ( movement > 0 ) {
|
|
1210
|
+
|
|
1211
|
+
size = Math.pow( this.scaleFactor, movement * screenNotches );
|
|
1212
|
+
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
this._v3_1.setFromMatrixPosition( this._cameraMatrixState );
|
|
1216
|
+
const x = this._v3_1.distanceTo( this._gizmos.position );
|
|
1217
|
+
let xNew = x / size; //distance between camera and gizmos if scale(size, scalepoint) would be performed
|
|
1218
|
+
|
|
1219
|
+
//check min and max distance
|
|
1220
|
+
xNew = MathUtils.clamp( xNew, this.minDistance, this.maxDistance );
|
|
1221
|
+
|
|
1222
|
+
const y = x * Math.tan( MathUtils.DEG2RAD * this._fovState * 0.5 );
|
|
1223
|
+
|
|
1224
|
+
//calculate new fov
|
|
1225
|
+
let newFov = MathUtils.RAD2DEG * ( Math.atan( y / xNew ) * 2 );
|
|
1226
|
+
|
|
1227
|
+
//check min and max fov
|
|
1228
|
+
newFov = MathUtils.clamp( newFov, this.minFov, this.maxFov );
|
|
1229
|
+
|
|
1230
|
+
const newDistance = y / Math.tan( MathUtils.DEG2RAD * ( newFov / 2 ) );
|
|
1231
|
+
size = x / newDistance;
|
|
1232
|
+
this._v3_2.setFromMatrixPosition( this._gizmoMatrixState );
|
|
1233
|
+
|
|
1234
|
+
this.setFov( newFov );
|
|
1235
|
+
this.applyTransformMatrix( this.scale( size, this._v3_2, false ) );
|
|
1236
|
+
|
|
1237
|
+
//adjusting distance
|
|
1238
|
+
_offset.copy( this._gizmos.position ).sub( this.object.position ).normalize().multiplyScalar( newDistance / x );
|
|
1239
|
+
this._m4_1.makeTranslation( _offset.x, _offset.y, _offset.z );
|
|
1240
|
+
|
|
1241
|
+
this.dispatchEvent( _changeEvent );
|
|
1242
|
+
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
onTriplePanEnd() {
|
|
1248
|
+
|
|
1249
|
+
this.updateTbState( STATE.IDLE, false );
|
|
1250
|
+
this.dispatchEvent( _endEvent );
|
|
1251
|
+
//this.dispatchEvent( _changeEvent );
|
|
1252
|
+
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
/**
|
|
1256
|
+
* Set _center's x/y coordinates.
|
|
1257
|
+
*
|
|
1258
|
+
* @private
|
|
1259
|
+
* @param {number} clientX - The x coordinate.
|
|
1260
|
+
* @param {number} clientY - The y coordinate.
|
|
1261
|
+
*/
|
|
1262
|
+
setCenter( clientX, clientY ) {
|
|
1263
|
+
|
|
1264
|
+
_center.x = clientX;
|
|
1265
|
+
_center.y = clientY;
|
|
1266
|
+
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
/**
|
|
1270
|
+
* Set default mouse actions.
|
|
1271
|
+
*
|
|
1272
|
+
* @private
|
|
1273
|
+
*/
|
|
1274
|
+
initializeMouseActions() {
|
|
1275
|
+
|
|
1276
|
+
this.setMouseAction( 'PAN', 0, 'CTRL' );
|
|
1277
|
+
this.setMouseAction( 'PAN', 2 );
|
|
1278
|
+
|
|
1279
|
+
this.setMouseAction( 'ROTATE', 0 );
|
|
1280
|
+
|
|
1281
|
+
this.setMouseAction( 'ZOOM', 'WHEEL' );
|
|
1282
|
+
this.setMouseAction( 'ZOOM', 1 );
|
|
1283
|
+
|
|
1284
|
+
this.setMouseAction( 'FOV', 'WHEEL', 'SHIFT' );
|
|
1285
|
+
this.setMouseAction( 'FOV', 1, 'SHIFT' );
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
/**
|
|
1291
|
+
* Compare two mouse actions.
|
|
1292
|
+
*
|
|
1293
|
+
* @private
|
|
1294
|
+
* @param {Object} action1 - The first mouse action.
|
|
1295
|
+
* @param {Object} action2 - The second mouse action.
|
|
1296
|
+
* @returns {boolean} `true` if action1 and action 2 are the same mouse action, `false` otherwise.
|
|
1297
|
+
*/
|
|
1298
|
+
compareMouseAction( action1, action2 ) {
|
|
1299
|
+
|
|
1300
|
+
if ( action1.operation == action2.operation ) {
|
|
1301
|
+
|
|
1302
|
+
if ( action1.mouse == action2.mouse && action1.key == action2.key ) {
|
|
1303
|
+
|
|
1304
|
+
return true;
|
|
1305
|
+
|
|
1306
|
+
} else {
|
|
1307
|
+
|
|
1308
|
+
return false;
|
|
1309
|
+
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
} else {
|
|
1313
|
+
|
|
1314
|
+
return false;
|
|
1315
|
+
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
/**
|
|
1321
|
+
* Set a new mouse action by specifying the operation to be performed and a mouse/key combination. In case of conflict, replaces the existing one.
|
|
1322
|
+
*
|
|
1323
|
+
* @param {'PAN'|'ROTATE'|'ZOOM'|'FOV'} operation - The operation to be performed ('PAN', 'ROTATE', 'ZOOM', 'FOV').
|
|
1324
|
+
* @param {0|1|2|'WHEEL'} mouse - A mouse button (0, 1, 2) or 'WHEEL' for wheel notches.
|
|
1325
|
+
* @param {?('CTRL'|'SHIFT')} [key=null] - The keyboard modifier ('CTRL', 'SHIFT') or null if key is not needed.
|
|
1326
|
+
* @returns {boolean} `true` if the mouse action has been successfully added, `false` otherwise.
|
|
1327
|
+
*/
|
|
1328
|
+
setMouseAction( operation, mouse, key = null ) {
|
|
1329
|
+
|
|
1330
|
+
const operationInput = [ 'PAN', 'ROTATE', 'ZOOM', 'FOV' ];
|
|
1331
|
+
const mouseInput = [ 0, 1, 2, 'WHEEL' ];
|
|
1332
|
+
const keyInput = [ 'CTRL', 'SHIFT', null ];
|
|
1333
|
+
let state;
|
|
1334
|
+
|
|
1335
|
+
if ( ! operationInput.includes( operation ) || ! mouseInput.includes( mouse ) || ! keyInput.includes( key ) ) {
|
|
1336
|
+
|
|
1337
|
+
//invalid parameters
|
|
1338
|
+
return false;
|
|
1339
|
+
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
if ( mouse == 'WHEEL' ) {
|
|
1343
|
+
|
|
1344
|
+
if ( operation != 'ZOOM' && operation != 'FOV' ) {
|
|
1345
|
+
|
|
1346
|
+
//cannot associate 2D operation to 1D input
|
|
1347
|
+
return false;
|
|
1348
|
+
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
switch ( operation ) {
|
|
1354
|
+
|
|
1355
|
+
case 'PAN':
|
|
1356
|
+
|
|
1357
|
+
state = STATE.PAN;
|
|
1358
|
+
break;
|
|
1359
|
+
|
|
1360
|
+
case 'ROTATE':
|
|
1361
|
+
|
|
1362
|
+
state = STATE.ROTATE;
|
|
1363
|
+
break;
|
|
1364
|
+
|
|
1365
|
+
case 'ZOOM':
|
|
1366
|
+
|
|
1367
|
+
state = STATE.SCALE;
|
|
1368
|
+
break;
|
|
1369
|
+
|
|
1370
|
+
case 'FOV':
|
|
1371
|
+
|
|
1372
|
+
state = STATE.FOV;
|
|
1373
|
+
break;
|
|
1374
|
+
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
const action = {
|
|
1378
|
+
|
|
1379
|
+
operation: operation,
|
|
1380
|
+
mouse: mouse,
|
|
1381
|
+
key: key,
|
|
1382
|
+
state: state
|
|
1383
|
+
|
|
1384
|
+
};
|
|
1385
|
+
|
|
1386
|
+
for ( let i = 0; i < this.mouseActions.length; i ++ ) {
|
|
1387
|
+
|
|
1388
|
+
if ( this.mouseActions[ i ].mouse == action.mouse && this.mouseActions[ i ].key == action.key ) {
|
|
1389
|
+
|
|
1390
|
+
this.mouseActions.splice( i, 1, action );
|
|
1391
|
+
return true;
|
|
1392
|
+
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
this.mouseActions.push( action );
|
|
1398
|
+
return true;
|
|
1399
|
+
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
/**
|
|
1403
|
+
* Remove a mouse action by specifying its mouse/key combination.
|
|
1404
|
+
*
|
|
1405
|
+
* @param {0|1|2|'WHEEL'} mouse - A mouse button (0, 1, 2) or 'WHEEL' for wheel notches.
|
|
1406
|
+
* @param {?('CTRL'|'SHIFT')} key - The keyboard modifier ('CTRL', 'SHIFT') or null if key is not needed.
|
|
1407
|
+
* @returns {boolean} `true` if the operation has been successfully removed, `false` otherwise.
|
|
1408
|
+
*/
|
|
1409
|
+
unsetMouseAction( mouse, key = null ) {
|
|
1410
|
+
|
|
1411
|
+
for ( let i = 0; i < this.mouseActions.length; i ++ ) {
|
|
1412
|
+
|
|
1413
|
+
if ( this.mouseActions[ i ].mouse == mouse && this.mouseActions[ i ].key == key ) {
|
|
1414
|
+
|
|
1415
|
+
this.mouseActions.splice( i, 1 );
|
|
1416
|
+
return true;
|
|
1417
|
+
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
return false;
|
|
1423
|
+
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
/**
|
|
1427
|
+
* Return the operation associated to a mouse/keyboard combination.
|
|
1428
|
+
*
|
|
1429
|
+
* @private
|
|
1430
|
+
* @param {0|1|2|'WHEEL'} mouse - Mouse button index (0, 1, 2) or 'WHEEL' for wheel notches.
|
|
1431
|
+
* @param {?('CTRL'|'SHIFT')} key - Keyboard modifier.
|
|
1432
|
+
* @returns {?('PAN'|'ROTATE'|'ZOOM'|'FOV')} The operation if it has been found, `null` otherwise.
|
|
1433
|
+
*/
|
|
1434
|
+
getOpFromAction( mouse, key ) {
|
|
1435
|
+
|
|
1436
|
+
let action;
|
|
1437
|
+
|
|
1438
|
+
for ( let i = 0; i < this.mouseActions.length; i ++ ) {
|
|
1439
|
+
|
|
1440
|
+
action = this.mouseActions[ i ];
|
|
1441
|
+
if ( action.mouse == mouse && action.key == key ) {
|
|
1442
|
+
|
|
1443
|
+
return action.operation;
|
|
1444
|
+
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
if ( key != null ) {
|
|
1450
|
+
|
|
1451
|
+
for ( let i = 0; i < this.mouseActions.length; i ++ ) {
|
|
1452
|
+
|
|
1453
|
+
action = this.mouseActions[ i ];
|
|
1454
|
+
if ( action.mouse == mouse && action.key == null ) {
|
|
1455
|
+
|
|
1456
|
+
return action.operation;
|
|
1457
|
+
|
|
1458
|
+
}
|
|
1459
|
+
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
return null;
|
|
1465
|
+
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
/**
|
|
1469
|
+
* Get the operation associated to mouse and key combination and returns the corresponding FSA state.
|
|
1470
|
+
*
|
|
1471
|
+
* @private
|
|
1472
|
+
* @param {0|1|2} mouse - Mouse button index (0, 1, 2)
|
|
1473
|
+
* @param {?('CTRL'|'SHIFT')} key - Keyboard modifier
|
|
1474
|
+
* @returns {?STATE} The FSA state obtained from the operation associated to mouse/keyboard combination.
|
|
1475
|
+
*/
|
|
1476
|
+
getOpStateFromAction( mouse, key ) {
|
|
1477
|
+
|
|
1478
|
+
let action;
|
|
1479
|
+
|
|
1480
|
+
for ( let i = 0; i < this.mouseActions.length; i ++ ) {
|
|
1481
|
+
|
|
1482
|
+
action = this.mouseActions[ i ];
|
|
1483
|
+
if ( action.mouse == mouse && action.key == key ) {
|
|
1484
|
+
|
|
1485
|
+
return action.state;
|
|
1486
|
+
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
if ( key != null ) {
|
|
1492
|
+
|
|
1493
|
+
for ( let i = 0; i < this.mouseActions.length; i ++ ) {
|
|
1494
|
+
|
|
1495
|
+
action = this.mouseActions[ i ];
|
|
1496
|
+
if ( action.mouse == mouse && action.key == null ) {
|
|
1497
|
+
|
|
1498
|
+
return action.state;
|
|
1499
|
+
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
return null;
|
|
1507
|
+
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
/**
|
|
1511
|
+
* Calculate the angle between two pointers.
|
|
1512
|
+
*
|
|
1513
|
+
* @private
|
|
1514
|
+
* @param {PointerEvent} p1 - The first pointer event.
|
|
1515
|
+
* @param {PointerEvent} p2 - The second pointer event.
|
|
1516
|
+
* @returns {number} The angle between two pointers in degrees.
|
|
1517
|
+
*/
|
|
1518
|
+
getAngle( p1, p2 ) {
|
|
1519
|
+
|
|
1520
|
+
return Math.atan2( p2.clientY - p1.clientY, p2.clientX - p1.clientX ) * 180 / Math.PI;
|
|
1521
|
+
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
/**
|
|
1525
|
+
* Updates a PointerEvent inside current pointerevents array.
|
|
1526
|
+
*
|
|
1527
|
+
* @private
|
|
1528
|
+
* @param {PointerEvent} event - The pointer event.
|
|
1529
|
+
*/
|
|
1530
|
+
updateTouchEvent( event ) {
|
|
1531
|
+
|
|
1532
|
+
for ( let i = 0; i < this._touchCurrent.length; i ++ ) {
|
|
1533
|
+
|
|
1534
|
+
if ( this._touchCurrent[ i ].pointerId == event.pointerId ) {
|
|
1535
|
+
|
|
1536
|
+
this._touchCurrent.splice( i, 1, event );
|
|
1537
|
+
break;
|
|
1538
|
+
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
/**
|
|
1546
|
+
* Applies a transformation matrix, to the camera and gizmos.
|
|
1547
|
+
*
|
|
1548
|
+
* @private
|
|
1549
|
+
* @param {Object} transformation - Object containing matrices to apply to camera and gizmos.
|
|
1550
|
+
*/
|
|
1551
|
+
applyTransformMatrix( transformation ) {
|
|
1552
|
+
|
|
1553
|
+
if ( transformation.camera != null ) {
|
|
1554
|
+
|
|
1555
|
+
this._m4_1.copy( this._cameraMatrixState ).premultiply( transformation.camera );
|
|
1556
|
+
this._m4_1.decompose( this.object.position, this.object.quaternion, this.object.scale );
|
|
1557
|
+
this.object.updateMatrix();
|
|
1558
|
+
|
|
1559
|
+
//update camera up vector
|
|
1560
|
+
if ( this._state == STATE.ROTATE || this._state == STATE.ZROTATE || this._state == STATE.ANIMATION_ROTATE ) {
|
|
1561
|
+
|
|
1562
|
+
this.object.up.copy( this._upState ).applyQuaternion( this.object.quaternion );
|
|
1563
|
+
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
if ( transformation.gizmos != null ) {
|
|
1569
|
+
|
|
1570
|
+
this._m4_1.copy( this._gizmoMatrixState ).premultiply( transformation.gizmos );
|
|
1571
|
+
this._m4_1.decompose( this._gizmos.position, this._gizmos.quaternion, this._gizmos.scale );
|
|
1572
|
+
this._gizmos.updateMatrix();
|
|
1573
|
+
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
if ( this._state == STATE.SCALE || this._state == STATE.FOCUS || this._state == STATE.ANIMATION_FOCUS ) {
|
|
1577
|
+
|
|
1578
|
+
this._tbRadius = this.calculateTbRadius( this.object );
|
|
1579
|
+
|
|
1580
|
+
if ( this.adjustNearFar ) {
|
|
1581
|
+
|
|
1582
|
+
const cameraDistance = this.object.position.distanceTo( this._gizmos.position );
|
|
1583
|
+
|
|
1584
|
+
const bb = new Box3();
|
|
1585
|
+
bb.setFromObject( this._gizmos );
|
|
1586
|
+
const sphere = new Sphere();
|
|
1587
|
+
bb.getBoundingSphere( sphere );
|
|
1588
|
+
|
|
1589
|
+
const adjustedNearPosition = Math.max( this._nearPos0, sphere.radius + sphere.center.length() );
|
|
1590
|
+
const regularNearPosition = cameraDistance - this._initialNear;
|
|
1591
|
+
|
|
1592
|
+
const minNearPos = Math.min( adjustedNearPosition, regularNearPosition );
|
|
1593
|
+
this.object.near = cameraDistance - minNearPos;
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
const adjustedFarPosition = Math.min( this._farPos0, - sphere.radius + sphere.center.length() );
|
|
1597
|
+
const regularFarPosition = cameraDistance - this._initialFar;
|
|
1598
|
+
|
|
1599
|
+
const minFarPos = Math.min( adjustedFarPosition, regularFarPosition );
|
|
1600
|
+
this.object.far = cameraDistance - minFarPos;
|
|
1601
|
+
|
|
1602
|
+
this.object.updateProjectionMatrix();
|
|
1603
|
+
|
|
1604
|
+
} else {
|
|
1605
|
+
|
|
1606
|
+
let update = false;
|
|
1607
|
+
|
|
1608
|
+
if ( this.object.near != this._initialNear ) {
|
|
1609
|
+
|
|
1610
|
+
this.object.near = this._initialNear;
|
|
1611
|
+
update = true;
|
|
1612
|
+
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
if ( this.object.far != this._initialFar ) {
|
|
1616
|
+
|
|
1617
|
+
this.object.far = this._initialFar;
|
|
1618
|
+
update = true;
|
|
1619
|
+
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
if ( update ) {
|
|
1623
|
+
|
|
1624
|
+
this.object.updateProjectionMatrix();
|
|
1625
|
+
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
/**
|
|
1635
|
+
* Calculates the angular speed.
|
|
1636
|
+
*
|
|
1637
|
+
* @private
|
|
1638
|
+
* @param {number} p0 - Position at t0.
|
|
1639
|
+
* @param {number} p1 - Position at t1.
|
|
1640
|
+
* @param {number} t0 - Initial time in milliseconds.
|
|
1641
|
+
* @param {number} t1 - Ending time in milliseconds.
|
|
1642
|
+
* @returns {number} The angular speed.
|
|
1643
|
+
*/
|
|
1644
|
+
calculateAngularSpeed( p0, p1, t0, t1 ) {
|
|
1645
|
+
|
|
1646
|
+
const s = p1 - p0;
|
|
1647
|
+
const t = ( t1 - t0 ) / 1000;
|
|
1648
|
+
if ( t == 0 ) {
|
|
1649
|
+
|
|
1650
|
+
return 0;
|
|
1651
|
+
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
return s / t;
|
|
1655
|
+
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
/**
|
|
1659
|
+
* Calculates the distance between two pointers.
|
|
1660
|
+
*
|
|
1661
|
+
* @private
|
|
1662
|
+
* @param {PointerEvent} p0 - The first pointer.
|
|
1663
|
+
* @param {PointerEvent} p1 - The second pointer.
|
|
1664
|
+
* @returns {number} The distance between the two pointers.
|
|
1665
|
+
*/
|
|
1666
|
+
calculatePointersDistance( p0, p1 ) {
|
|
1667
|
+
|
|
1668
|
+
return Math.sqrt( Math.pow( p1.clientX - p0.clientX, 2 ) + Math.pow( p1.clientY - p0.clientY, 2 ) );
|
|
1669
|
+
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
/**
|
|
1673
|
+
* Calculates the rotation axis as the vector perpendicular between two vectors.
|
|
1674
|
+
*
|
|
1675
|
+
* @private
|
|
1676
|
+
* @param {Vector3} vec1 - The first vector.
|
|
1677
|
+
* @param {Vector3} vec2 - The second vector.
|
|
1678
|
+
* @returns {Vector3} The normalized rotation axis.
|
|
1679
|
+
*/
|
|
1680
|
+
calculateRotationAxis( vec1, vec2 ) {
|
|
1681
|
+
|
|
1682
|
+
this._rotationMatrix.extractRotation( this._cameraMatrixState );
|
|
1683
|
+
this._quat.setFromRotationMatrix( this._rotationMatrix );
|
|
1684
|
+
|
|
1685
|
+
this._rotationAxis.crossVectors( vec1, vec2 ).applyQuaternion( this._quat );
|
|
1686
|
+
return this._rotationAxis.normalize().clone();
|
|
1687
|
+
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
/**
|
|
1691
|
+
* Calculates the trackball radius so that gizmo's diameter will be 2/3 of the minimum side of the camera frustum.
|
|
1692
|
+
*
|
|
1693
|
+
* @private
|
|
1694
|
+
* @param {Camera} camera - The camera.
|
|
1695
|
+
* @returns {number} The trackball radius.
|
|
1696
|
+
*/
|
|
1697
|
+
calculateTbRadius( camera ) {
|
|
1698
|
+
|
|
1699
|
+
const distance = camera.position.distanceTo( this._gizmos.position );
|
|
1700
|
+
|
|
1701
|
+
if ( camera.type == 'PerspectiveCamera' ) {
|
|
1702
|
+
|
|
1703
|
+
const halfFovV = MathUtils.DEG2RAD * camera.fov * 0.5; //vertical fov/2 in radians
|
|
1704
|
+
const halfFovH = Math.atan( ( camera.aspect ) * Math.tan( halfFovV ) ); //horizontal fov/2 in radians
|
|
1705
|
+
return Math.tan( Math.min( halfFovV, halfFovH ) ) * distance * this.radiusFactor;
|
|
1706
|
+
|
|
1707
|
+
} else if ( camera.type == 'OrthographicCamera' ) {
|
|
1708
|
+
|
|
1709
|
+
return Math.min( camera.top, camera.right ) * this.radiusFactor;
|
|
1710
|
+
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
/**
|
|
1716
|
+
* Focus operation consist of positioning the point of interest in front of the camera and a slightly zoom in.
|
|
1717
|
+
*
|
|
1718
|
+
* @private
|
|
1719
|
+
* @param {Vector3} point - The point of interest.
|
|
1720
|
+
* @param {number} size - Scale factor.
|
|
1721
|
+
* @param {number} [amount=1] - Amount of operation to be completed (used for focus animations, default is complete full operation).
|
|
1722
|
+
*/
|
|
1723
|
+
focus( point, size, amount = 1 ) {
|
|
1724
|
+
|
|
1725
|
+
//move center of camera (along with gizmos) towards point of interest
|
|
1726
|
+
_offset.copy( point ).sub( this._gizmos.position ).multiplyScalar( amount );
|
|
1727
|
+
this._translationMatrix.makeTranslation( _offset.x, _offset.y, _offset.z );
|
|
1728
|
+
|
|
1729
|
+
_gizmoMatrixStateTemp.copy( this._gizmoMatrixState );
|
|
1730
|
+
this._gizmoMatrixState.premultiply( this._translationMatrix );
|
|
1731
|
+
this._gizmoMatrixState.decompose( this._gizmos.position, this._gizmos.quaternion, this._gizmos.scale );
|
|
1732
|
+
|
|
1733
|
+
_cameraMatrixStateTemp.copy( this._cameraMatrixState );
|
|
1734
|
+
this._cameraMatrixState.premultiply( this._translationMatrix );
|
|
1735
|
+
this._cameraMatrixState.decompose( this.object.position, this.object.quaternion, this.object.scale );
|
|
1736
|
+
|
|
1737
|
+
//apply zoom
|
|
1738
|
+
if ( this.enableZoom ) {
|
|
1739
|
+
|
|
1740
|
+
this.applyTransformMatrix( this.scale( size, this._gizmos.position ) );
|
|
1741
|
+
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
this._gizmoMatrixState.copy( _gizmoMatrixStateTemp );
|
|
1745
|
+
this._cameraMatrixState.copy( _cameraMatrixStateTemp );
|
|
1746
|
+
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
/**
|
|
1750
|
+
* Creates a grid if necessary and adds it to the scene.
|
|
1751
|
+
*
|
|
1752
|
+
* @private
|
|
1753
|
+
*/
|
|
1754
|
+
drawGrid() {
|
|
1755
|
+
|
|
1756
|
+
if ( this.scene != null ) {
|
|
1757
|
+
|
|
1758
|
+
const color = 0x888888;
|
|
1759
|
+
const multiplier = 3;
|
|
1760
|
+
let size, divisions, maxLength, tick;
|
|
1761
|
+
|
|
1762
|
+
if ( this.object.isOrthographicCamera ) {
|
|
1763
|
+
|
|
1764
|
+
const width = this.object.right - this.object.left;
|
|
1765
|
+
const height = this.object.bottom - this.object.top;
|
|
1766
|
+
|
|
1767
|
+
maxLength = Math.max( width, height );
|
|
1768
|
+
tick = maxLength / 20;
|
|
1769
|
+
|
|
1770
|
+
size = maxLength / this.object.zoom * multiplier;
|
|
1771
|
+
divisions = size / tick * this.object.zoom;
|
|
1772
|
+
|
|
1773
|
+
} else if ( this.object.isPerspectiveCamera ) {
|
|
1774
|
+
|
|
1775
|
+
const distance = this.object.position.distanceTo( this._gizmos.position );
|
|
1776
|
+
const halfFovV = MathUtils.DEG2RAD * this.object.fov * 0.5;
|
|
1777
|
+
const halfFovH = Math.atan( ( this.object.aspect ) * Math.tan( halfFovV ) );
|
|
1778
|
+
|
|
1779
|
+
maxLength = Math.tan( Math.max( halfFovV, halfFovH ) ) * distance * 2;
|
|
1780
|
+
tick = maxLength / 20;
|
|
1781
|
+
|
|
1782
|
+
size = maxLength * multiplier;
|
|
1783
|
+
divisions = size / tick;
|
|
1784
|
+
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
if ( this._grid == null ) {
|
|
1788
|
+
|
|
1789
|
+
this._grid = new GridHelper( size, divisions, color, color );
|
|
1790
|
+
this._grid.position.copy( this._gizmos.position );
|
|
1791
|
+
this._gridPosition.copy( this._grid.position );
|
|
1792
|
+
this._grid.quaternion.copy( this.object.quaternion );
|
|
1793
|
+
this._grid.rotateX( Math.PI * 0.5 );
|
|
1794
|
+
|
|
1795
|
+
this.scene.add( this._grid );
|
|
1796
|
+
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
dispose() {
|
|
1804
|
+
|
|
1805
|
+
if ( this._animationId != - 1 ) {
|
|
1806
|
+
|
|
1807
|
+
window.cancelAnimationFrame( this._animationId );
|
|
1808
|
+
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
this.disconnect();
|
|
1812
|
+
|
|
1813
|
+
if ( this.scene !== null ) this.scene.remove( this._gizmos );
|
|
1814
|
+
this.disposeGrid();
|
|
1815
|
+
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
/**
|
|
1819
|
+
* Removes the grid from the scene.
|
|
1820
|
+
*/
|
|
1821
|
+
disposeGrid() {
|
|
1822
|
+
|
|
1823
|
+
if ( this._grid != null && this.scene != null ) {
|
|
1824
|
+
|
|
1825
|
+
this.scene.remove( this._grid );
|
|
1826
|
+
this._grid = null;
|
|
1827
|
+
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
/**
|
|
1833
|
+
* Computes the easing out cubic function for ease out effect in animation.
|
|
1834
|
+
*
|
|
1835
|
+
* @private
|
|
1836
|
+
* @param {number} t - The absolute progress of the animation in the bound of `0` (beginning of the) and `1` (ending of animation).
|
|
1837
|
+
* @returns {number} Result of easing out cubic at time `t`.
|
|
1838
|
+
*/
|
|
1839
|
+
easeOutCubic( t ) {
|
|
1840
|
+
|
|
1841
|
+
return 1 - Math.pow( 1 - t, 3 );
|
|
1842
|
+
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
/**
|
|
1846
|
+
* Makes rotation gizmos more or less visible.
|
|
1847
|
+
*
|
|
1848
|
+
* @param {boolean} isActive - If set to `true`, gizmos are more visible.
|
|
1849
|
+
*/
|
|
1850
|
+
activateGizmos( isActive ) {
|
|
1851
|
+
|
|
1852
|
+
const gizmoX = this._gizmos.children[ 0 ];
|
|
1853
|
+
const gizmoY = this._gizmos.children[ 1 ];
|
|
1854
|
+
const gizmoZ = this._gizmos.children[ 2 ];
|
|
1855
|
+
|
|
1856
|
+
if ( isActive ) {
|
|
1857
|
+
|
|
1858
|
+
gizmoX.material.setValues( { opacity: 1 } );
|
|
1859
|
+
gizmoY.material.setValues( { opacity: 1 } );
|
|
1860
|
+
gizmoZ.material.setValues( { opacity: 1 } );
|
|
1861
|
+
|
|
1862
|
+
} else {
|
|
1863
|
+
|
|
1864
|
+
gizmoX.material.setValues( { opacity: 0.6 } );
|
|
1865
|
+
gizmoY.material.setValues( { opacity: 0.6 } );
|
|
1866
|
+
gizmoZ.material.setValues( { opacity: 0.6 } );
|
|
1867
|
+
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
/**
|
|
1873
|
+
* Calculates the cursor position in NDC.
|
|
1874
|
+
*
|
|
1875
|
+
* @private
|
|
1876
|
+
* @param {number} cursorX - Cursor horizontal coordinate within the canvas.
|
|
1877
|
+
* @param {number} cursorY - Cursor vertical coordinate within the canvas.
|
|
1878
|
+
* @param {HTMLElement} canvas - The canvas where the renderer draws its output.
|
|
1879
|
+
* @returns {Vector2} Cursor normalized position inside the canvas.
|
|
1880
|
+
*/
|
|
1881
|
+
getCursorNDC( cursorX, cursorY, canvas ) {
|
|
1882
|
+
|
|
1883
|
+
const canvasRect = canvas.getBoundingClientRect();
|
|
1884
|
+
this._v2_1.setX( ( ( cursorX - canvasRect.left ) / canvasRect.width ) * 2 - 1 );
|
|
1885
|
+
this._v2_1.setY( ( ( canvasRect.bottom - cursorY ) / canvasRect.height ) * 2 - 1 );
|
|
1886
|
+
return this._v2_1.clone();
|
|
1887
|
+
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
/**
|
|
1891
|
+
* Calculates the cursor position inside the canvas x/y coordinates with the origin being in the center of the canvas.
|
|
1892
|
+
*
|
|
1893
|
+
* @private
|
|
1894
|
+
* @param {number} cursorX - Cursor horizontal coordinate within the canvas.
|
|
1895
|
+
* @param {number} cursorY - Cursor vertical coordinate within the canvas.
|
|
1896
|
+
* @param {HTMLElement} canvas - The canvas where the renderer draws its output.
|
|
1897
|
+
* @returns {Vector2} Cursor position inside the canvas.
|
|
1898
|
+
*/
|
|
1899
|
+
getCursorPosition( cursorX, cursorY, canvas ) {
|
|
1900
|
+
|
|
1901
|
+
this._v2_1.copy( this.getCursorNDC( cursorX, cursorY, canvas ) );
|
|
1902
|
+
this._v2_1.x *= ( this.object.right - this.object.left ) * 0.5;
|
|
1903
|
+
this._v2_1.y *= ( this.object.top - this.object.bottom ) * 0.5;
|
|
1904
|
+
return this._v2_1.clone();
|
|
1905
|
+
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
/**
|
|
1909
|
+
* Sets the camera to be controlled. Must be called in order to set a new camera to be controlled.
|
|
1910
|
+
*
|
|
1911
|
+
* @param {Camera} camera - The camera to be controlled.
|
|
1912
|
+
*/
|
|
1913
|
+
setCamera( camera ) {
|
|
1914
|
+
|
|
1915
|
+
camera.lookAt( this.target );
|
|
1916
|
+
camera.updateMatrix();
|
|
1917
|
+
|
|
1918
|
+
//setting state
|
|
1919
|
+
if ( camera.type == 'PerspectiveCamera' ) {
|
|
1920
|
+
|
|
1921
|
+
this._fov0 = camera.fov;
|
|
1922
|
+
this._fovState = camera.fov;
|
|
1923
|
+
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
this._cameraMatrixState0.copy( camera.matrix );
|
|
1927
|
+
this._cameraMatrixState.copy( this._cameraMatrixState0 );
|
|
1928
|
+
this._cameraProjectionState.copy( camera.projectionMatrix );
|
|
1929
|
+
this._zoom0 = camera.zoom;
|
|
1930
|
+
this._zoomState = this._zoom0;
|
|
1931
|
+
|
|
1932
|
+
this._initialNear = camera.near;
|
|
1933
|
+
this._nearPos0 = camera.position.distanceTo( this.target ) - camera.near;
|
|
1934
|
+
this._nearPos = this._initialNear;
|
|
1935
|
+
|
|
1936
|
+
this._initialFar = camera.far;
|
|
1937
|
+
this._farPos0 = camera.position.distanceTo( this.target ) - camera.far;
|
|
1938
|
+
this._farPos = this._initialFar;
|
|
1939
|
+
|
|
1940
|
+
this._up0.copy( camera.up );
|
|
1941
|
+
this._upState.copy( camera.up );
|
|
1942
|
+
|
|
1943
|
+
this.object = camera;
|
|
1944
|
+
this.object.updateProjectionMatrix();
|
|
1945
|
+
|
|
1946
|
+
//making gizmos
|
|
1947
|
+
this._tbRadius = this.calculateTbRadius( camera );
|
|
1948
|
+
this.makeGizmos( this.target, this._tbRadius );
|
|
1949
|
+
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
/**
|
|
1953
|
+
* Sets gizmos visibility.
|
|
1954
|
+
*
|
|
1955
|
+
* @param {boolean} value - Value of gizmos visibility.
|
|
1956
|
+
*/
|
|
1957
|
+
setGizmosVisible( value ) {
|
|
1958
|
+
|
|
1959
|
+
this._gizmos.visible = value;
|
|
1960
|
+
this.dispatchEvent( _changeEvent );
|
|
1961
|
+
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
/**
|
|
1965
|
+
* Sets gizmos radius factor and redraws gizmos.
|
|
1966
|
+
*
|
|
1967
|
+
* @param {number} value - Value of radius factor.
|
|
1968
|
+
*/
|
|
1969
|
+
setTbRadius( value ) {
|
|
1970
|
+
|
|
1971
|
+
this.radiusFactor = value;
|
|
1972
|
+
this._tbRadius = this.calculateTbRadius( this.object );
|
|
1973
|
+
|
|
1974
|
+
const curve = new EllipseCurve( 0, 0, this._tbRadius, this._tbRadius );
|
|
1975
|
+
const points = curve.getPoints( this._curvePts );
|
|
1976
|
+
const curveGeometry = new BufferGeometry().setFromPoints( points );
|
|
1977
|
+
|
|
1978
|
+
|
|
1979
|
+
for ( const gizmo in this._gizmos.children ) {
|
|
1980
|
+
|
|
1981
|
+
this._gizmos.children[ gizmo ].geometry = curveGeometry;
|
|
1982
|
+
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
this.dispatchEvent( _changeEvent );
|
|
1986
|
+
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
/**
|
|
1990
|
+
* Creates the rotation gizmos matching trackball center and radius.
|
|
1991
|
+
*
|
|
1992
|
+
* @private
|
|
1993
|
+
* @param {Vector3} tbCenter - The trackball center.
|
|
1994
|
+
* @param {number} tbRadius - The trackball radius.
|
|
1995
|
+
*/
|
|
1996
|
+
makeGizmos( tbCenter, tbRadius ) {
|
|
1997
|
+
|
|
1998
|
+
const curve = new EllipseCurve( 0, 0, tbRadius, tbRadius );
|
|
1999
|
+
const points = curve.getPoints( this._curvePts );
|
|
2000
|
+
|
|
2001
|
+
//geometry
|
|
2002
|
+
const curveGeometry = new BufferGeometry().setFromPoints( points );
|
|
2003
|
+
|
|
2004
|
+
//material
|
|
2005
|
+
const curveMaterialX = new LineBasicMaterial( { color: 0xff8080, fog: false, transparent: true, opacity: 0.6 } );
|
|
2006
|
+
const curveMaterialY = new LineBasicMaterial( { color: 0x80ff80, fog: false, transparent: true, opacity: 0.6 } );
|
|
2007
|
+
const curveMaterialZ = new LineBasicMaterial( { color: 0x8080ff, fog: false, transparent: true, opacity: 0.6 } );
|
|
2008
|
+
|
|
2009
|
+
//line
|
|
2010
|
+
const gizmoX = new Line( curveGeometry, curveMaterialX );
|
|
2011
|
+
const gizmoY = new Line( curveGeometry, curveMaterialY );
|
|
2012
|
+
const gizmoZ = new Line( curveGeometry, curveMaterialZ );
|
|
2013
|
+
|
|
2014
|
+
const rotation = Math.PI * 0.5;
|
|
2015
|
+
gizmoX.rotation.y = rotation;
|
|
2016
|
+
gizmoY.rotation.x = rotation;
|
|
2017
|
+
|
|
2018
|
+
|
|
2019
|
+
//setting state
|
|
2020
|
+
this._gizmoMatrixState0.identity().setPosition( tbCenter );
|
|
2021
|
+
this._gizmoMatrixState.copy( this._gizmoMatrixState0 );
|
|
2022
|
+
|
|
2023
|
+
if ( this.object.zoom !== 1 ) {
|
|
2024
|
+
|
|
2025
|
+
//adapt gizmos size to camera zoom
|
|
2026
|
+
const size = 1 / this.object.zoom;
|
|
2027
|
+
this._scaleMatrix.makeScale( size, size, size );
|
|
2028
|
+
this._translationMatrix.makeTranslation( - tbCenter.x, - tbCenter.y, - tbCenter.z );
|
|
2029
|
+
|
|
2030
|
+
this._gizmoMatrixState.premultiply( this._translationMatrix ).premultiply( this._scaleMatrix );
|
|
2031
|
+
this._translationMatrix.makeTranslation( tbCenter.x, tbCenter.y, tbCenter.z );
|
|
2032
|
+
this._gizmoMatrixState.premultiply( this._translationMatrix );
|
|
2033
|
+
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
this._gizmoMatrixState.decompose( this._gizmos.position, this._gizmos.quaternion, this._gizmos.scale );
|
|
2037
|
+
|
|
2038
|
+
//
|
|
2039
|
+
|
|
2040
|
+
this._gizmos.traverse( function ( object ) {
|
|
2041
|
+
|
|
2042
|
+
if ( object.isLine ) {
|
|
2043
|
+
|
|
2044
|
+
object.geometry.dispose();
|
|
2045
|
+
object.material.dispose();
|
|
2046
|
+
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
} );
|
|
2050
|
+
|
|
2051
|
+
this._gizmos.clear();
|
|
2052
|
+
|
|
2053
|
+
//
|
|
2054
|
+
|
|
2055
|
+
this._gizmos.add( gizmoX );
|
|
2056
|
+
this._gizmos.add( gizmoY );
|
|
2057
|
+
this._gizmos.add( gizmoZ );
|
|
2058
|
+
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
/**
|
|
2062
|
+
* Performs animation for focus operation.
|
|
2063
|
+
*
|
|
2064
|
+
* @private
|
|
2065
|
+
* @param {number} time - Instant in which this function is called as performance.now().
|
|
2066
|
+
* @param {Vector3} point - Point of interest for focus operation.
|
|
2067
|
+
* @param {Matrix4} cameraMatrix - Camera matrix.
|
|
2068
|
+
* @param {Matrix4} gizmoMatrix - Gizmos matrix.
|
|
2069
|
+
*/
|
|
2070
|
+
onFocusAnim( time, point, cameraMatrix, gizmoMatrix ) {
|
|
2071
|
+
|
|
2072
|
+
if ( this._timeStart == - 1 ) {
|
|
2073
|
+
|
|
2074
|
+
//animation start
|
|
2075
|
+
this._timeStart = time;
|
|
2076
|
+
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
if ( this._state == STATE.ANIMATION_FOCUS ) {
|
|
2080
|
+
|
|
2081
|
+
const deltaTime = time - this._timeStart;
|
|
2082
|
+
const animTime = deltaTime / this.focusAnimationTime;
|
|
2083
|
+
|
|
2084
|
+
this._gizmoMatrixState.copy( gizmoMatrix );
|
|
2085
|
+
|
|
2086
|
+
if ( animTime >= 1 ) {
|
|
2087
|
+
|
|
2088
|
+
//animation end
|
|
2089
|
+
|
|
2090
|
+
this._gizmoMatrixState.decompose( this._gizmos.position, this._gizmos.quaternion, this._gizmos.scale );
|
|
2091
|
+
|
|
2092
|
+
this.focus( point, this.scaleFactor );
|
|
2093
|
+
|
|
2094
|
+
this._timeStart = - 1;
|
|
2095
|
+
this.updateTbState( STATE.IDLE, false );
|
|
2096
|
+
this.activateGizmos( false );
|
|
2097
|
+
|
|
2098
|
+
this.dispatchEvent( _changeEvent );
|
|
2099
|
+
|
|
2100
|
+
} else {
|
|
2101
|
+
|
|
2102
|
+
const amount = this.easeOutCubic( animTime );
|
|
2103
|
+
const size = ( ( 1 - amount ) + ( this.scaleFactor * amount ) );
|
|
2104
|
+
|
|
2105
|
+
this._gizmoMatrixState.decompose( this._gizmos.position, this._gizmos.quaternion, this._gizmos.scale );
|
|
2106
|
+
this.focus( point, size, amount );
|
|
2107
|
+
|
|
2108
|
+
this.dispatchEvent( _changeEvent );
|
|
2109
|
+
const self = this;
|
|
2110
|
+
this._animationId = window.requestAnimationFrame( function ( t ) {
|
|
2111
|
+
|
|
2112
|
+
self.onFocusAnim( t, point, cameraMatrix, gizmoMatrix.clone() );
|
|
2113
|
+
|
|
2114
|
+
} );
|
|
2115
|
+
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
} else {
|
|
2119
|
+
|
|
2120
|
+
//interrupt animation
|
|
2121
|
+
|
|
2122
|
+
this._animationId = - 1;
|
|
2123
|
+
this._timeStart = - 1;
|
|
2124
|
+
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
/**
|
|
2130
|
+
* Performs animation for rotation operation.
|
|
2131
|
+
*
|
|
2132
|
+
* @private
|
|
2133
|
+
* @param {number} time - Instant in which this function is called as performance.now().
|
|
2134
|
+
* @param {Vector3} rotationAxis - Rotation axis.
|
|
2135
|
+
* @param {number} w0 - Initial angular velocity.
|
|
2136
|
+
*/
|
|
2137
|
+
onRotationAnim( time, rotationAxis, w0 ) {
|
|
2138
|
+
|
|
2139
|
+
if ( this._timeStart == - 1 ) {
|
|
2140
|
+
|
|
2141
|
+
//animation start
|
|
2142
|
+
this._anglePrev = 0;
|
|
2143
|
+
this._angleCurrent = 0;
|
|
2144
|
+
this._timeStart = time;
|
|
2145
|
+
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
if ( this._state == STATE.ANIMATION_ROTATE ) {
|
|
2149
|
+
|
|
2150
|
+
//w = w0 + alpha * t
|
|
2151
|
+
const deltaTime = ( time - this._timeStart ) / 1000;
|
|
2152
|
+
const w = w0 + ( ( - this.dampingFactor ) * deltaTime );
|
|
2153
|
+
|
|
2154
|
+
if ( w > 0 ) {
|
|
2155
|
+
|
|
2156
|
+
//tetha = 0.5 * alpha * t^2 + w0 * t + tetha0
|
|
2157
|
+
this._angleCurrent = 0.5 * ( - this.dampingFactor ) * Math.pow( deltaTime, 2 ) + w0 * deltaTime + 0;
|
|
2158
|
+
this.applyTransformMatrix( this.rotate( rotationAxis, this._angleCurrent ) );
|
|
2159
|
+
this.dispatchEvent( _changeEvent );
|
|
2160
|
+
const self = this;
|
|
2161
|
+
this._animationId = window.requestAnimationFrame( function ( t ) {
|
|
2162
|
+
|
|
2163
|
+
self.onRotationAnim( t, rotationAxis, w0 );
|
|
2164
|
+
|
|
2165
|
+
} );
|
|
2166
|
+
|
|
2167
|
+
} else {
|
|
2168
|
+
|
|
2169
|
+
this._animationId = - 1;
|
|
2170
|
+
this._timeStart = - 1;
|
|
2171
|
+
|
|
2172
|
+
this.updateTbState( STATE.IDLE, false );
|
|
2173
|
+
this.activateGizmos( false );
|
|
2174
|
+
|
|
2175
|
+
this.dispatchEvent( _changeEvent );
|
|
2176
|
+
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
} else {
|
|
2180
|
+
|
|
2181
|
+
//interrupt animation
|
|
2182
|
+
|
|
2183
|
+
this._animationId = - 1;
|
|
2184
|
+
this._timeStart = - 1;
|
|
2185
|
+
|
|
2186
|
+
if ( this._state != STATE.ROTATE ) {
|
|
2187
|
+
|
|
2188
|
+
this.activateGizmos( false );
|
|
2189
|
+
this.dispatchEvent( _changeEvent );
|
|
2190
|
+
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
|
|
2198
|
+
/**
|
|
2199
|
+
* Performs pan operation moving camera between two points.
|
|
2200
|
+
*
|
|
2201
|
+
* @private
|
|
2202
|
+
* @param {Vector3} p0 - Initial point.
|
|
2203
|
+
* @param {Vector3} p1 - Ending point.
|
|
2204
|
+
* @param {boolean} [adjust=false] - If movement should be adjusted considering camera distance (Perspective only).
|
|
2205
|
+
* @returns {Object}
|
|
2206
|
+
*/
|
|
2207
|
+
pan( p0, p1, adjust = false ) {
|
|
2208
|
+
|
|
2209
|
+
const movement = p0.clone().sub( p1 );
|
|
2210
|
+
|
|
2211
|
+
if ( this.object.isOrthographicCamera ) {
|
|
2212
|
+
|
|
2213
|
+
//adjust movement amount
|
|
2214
|
+
movement.multiplyScalar( 1 / this.object.zoom );
|
|
2215
|
+
|
|
2216
|
+
} else if ( this.object.isPerspectiveCamera && adjust ) {
|
|
2217
|
+
|
|
2218
|
+
//adjust movement amount
|
|
2219
|
+
this._v3_1.setFromMatrixPosition( this._cameraMatrixState0 ); //camera's initial position
|
|
2220
|
+
this._v3_2.setFromMatrixPosition( this._gizmoMatrixState0 ); //gizmo's initial position
|
|
2221
|
+
const distanceFactor = this._v3_1.distanceTo( this._v3_2 ) / this.object.position.distanceTo( this._gizmos.position );
|
|
2222
|
+
movement.multiplyScalar( 1 / distanceFactor );
|
|
2223
|
+
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
this._v3_1.set( movement.x, movement.y, 0 ).applyQuaternion( this.object.quaternion );
|
|
2227
|
+
|
|
2228
|
+
this._m4_1.makeTranslation( this._v3_1.x, this._v3_1.y, this._v3_1.z );
|
|
2229
|
+
|
|
2230
|
+
this.setTransformationMatrices( this._m4_1, this._m4_1 );
|
|
2231
|
+
return _transformation;
|
|
2232
|
+
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
/**
|
|
2236
|
+
* Resets the controls.
|
|
2237
|
+
*/
|
|
2238
|
+
reset() {
|
|
2239
|
+
|
|
2240
|
+
this.target.copy( this._target0 );
|
|
2241
|
+
this.object.zoom = this._zoom0;
|
|
2242
|
+
|
|
2243
|
+
if ( this.object.isPerspectiveCamera ) {
|
|
2244
|
+
|
|
2245
|
+
this.object.fov = this._fov0;
|
|
2246
|
+
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
this.object.near = this._nearPos;
|
|
2250
|
+
this.object.far = this._farPos;
|
|
2251
|
+
this._cameraMatrixState.copy( this._cameraMatrixState0 );
|
|
2252
|
+
this._cameraMatrixState.decompose( this.object.position, this.object.quaternion, this.object.scale );
|
|
2253
|
+
this.object.up.copy( this._up0 );
|
|
2254
|
+
|
|
2255
|
+
this.object.updateMatrix();
|
|
2256
|
+
this.object.updateProjectionMatrix();
|
|
2257
|
+
|
|
2258
|
+
this._gizmoMatrixState.copy( this._gizmoMatrixState0 );
|
|
2259
|
+
this._gizmoMatrixState0.decompose( this._gizmos.position, this._gizmos.quaternion, this._gizmos.scale );
|
|
2260
|
+
this._gizmos.updateMatrix();
|
|
2261
|
+
|
|
2262
|
+
this._tbRadius = this.calculateTbRadius( this.object );
|
|
2263
|
+
this.makeGizmos( this._gizmos.position, this._tbRadius );
|
|
2264
|
+
|
|
2265
|
+
this.object.lookAt( this._gizmos.position );
|
|
2266
|
+
|
|
2267
|
+
this.updateTbState( STATE.IDLE, false );
|
|
2268
|
+
|
|
2269
|
+
this.dispatchEvent( _changeEvent );
|
|
2270
|
+
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
/**
|
|
2274
|
+
* Rotates the camera around an axis passing by trackball's center.
|
|
2275
|
+
*
|
|
2276
|
+
* @private
|
|
2277
|
+
* @param {Vector3} axis - Rotation axis.
|
|
2278
|
+
* @param {number} angle - Angle in radians.
|
|
2279
|
+
* @returns {Object} Object with 'camera' field containing transformation matrix resulting from the operation to be applied to the camera.
|
|
2280
|
+
*/
|
|
2281
|
+
rotate( axis, angle ) {
|
|
2282
|
+
|
|
2283
|
+
const point = this._gizmos.position; //rotation center
|
|
2284
|
+
this._translationMatrix.makeTranslation( - point.x, - point.y, - point.z );
|
|
2285
|
+
this._rotationMatrix.makeRotationAxis( axis, - angle );
|
|
2286
|
+
|
|
2287
|
+
//rotate camera
|
|
2288
|
+
this._m4_1.makeTranslation( point.x, point.y, point.z );
|
|
2289
|
+
this._m4_1.multiply( this._rotationMatrix );
|
|
2290
|
+
this._m4_1.multiply( this._translationMatrix );
|
|
2291
|
+
|
|
2292
|
+
this.setTransformationMatrices( this._m4_1 );
|
|
2293
|
+
|
|
2294
|
+
return _transformation;
|
|
2295
|
+
|
|
2296
|
+
}
|
|
2297
|
+
|
|
2298
|
+
/**
|
|
2299
|
+
* Copy the current state to clipboard (as a readable JSON text).
|
|
2300
|
+
*/
|
|
2301
|
+
copyState() {
|
|
2302
|
+
|
|
2303
|
+
let state;
|
|
2304
|
+
if ( this.object.isOrthographicCamera ) {
|
|
2305
|
+
|
|
2306
|
+
state = JSON.stringify( {
|
|
2307
|
+
arcballState: {
|
|
2308
|
+
cameraFar: this.object.far,
|
|
2309
|
+
cameraMatrix: this.object.matrix,
|
|
2310
|
+
cameraNear: this.object.near,
|
|
2311
|
+
cameraUp: this.object.up,
|
|
2312
|
+
cameraZoom: this.object.zoom,
|
|
2313
|
+
gizmoMatrix: this._gizmos.matrix,
|
|
2314
|
+
target: this.target
|
|
2315
|
+
|
|
2316
|
+
}
|
|
2317
|
+
} );
|
|
2318
|
+
|
|
2319
|
+
} else if ( this.object.isPerspectiveCamera ) {
|
|
2320
|
+
|
|
2321
|
+
state = JSON.stringify( {
|
|
2322
|
+
arcballState: {
|
|
2323
|
+
cameraFar: this.object.far,
|
|
2324
|
+
cameraFov: this.object.fov,
|
|
2325
|
+
cameraMatrix: this.object.matrix,
|
|
2326
|
+
cameraNear: this.object.near,
|
|
2327
|
+
cameraUp: this.object.up,
|
|
2328
|
+
cameraZoom: this.object.zoom,
|
|
2329
|
+
gizmoMatrix: this._gizmos.matrix,
|
|
2330
|
+
target: this.target
|
|
2331
|
+
|
|
2332
|
+
}
|
|
2333
|
+
} );
|
|
2334
|
+
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
navigator.clipboard.writeText( state );
|
|
2338
|
+
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
/**
|
|
2342
|
+
* Set the controls state from the clipboard, assumes that the clipboard stores a JSON
|
|
2343
|
+
* text as saved from `copyState()`.
|
|
2344
|
+
*/
|
|
2345
|
+
pasteState() {
|
|
2346
|
+
|
|
2347
|
+
const self = this;
|
|
2348
|
+
navigator.clipboard.readText().then( function resolved( value ) {
|
|
2349
|
+
|
|
2350
|
+
self.setStateFromJSON( value );
|
|
2351
|
+
|
|
2352
|
+
} );
|
|
2353
|
+
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
/**
|
|
2357
|
+
* Saves the current state of the control. This can later be recover with `reset()`.
|
|
2358
|
+
*/
|
|
2359
|
+
saveState() {
|
|
2360
|
+
|
|
2361
|
+
this.object.updateMatrix();
|
|
2362
|
+
this._gizmos.updateMatrix();
|
|
2363
|
+
|
|
2364
|
+
this._target0.copy( this.target );
|
|
2365
|
+
this._cameraMatrixState0.copy( this.object.matrix );
|
|
2366
|
+
this._gizmoMatrixState0.copy( this._gizmos.matrix );
|
|
2367
|
+
this._nearPos = this.object.near;
|
|
2368
|
+
this._farPos = this.object.far;
|
|
2369
|
+
this._zoom0 = this.object.zoom;
|
|
2370
|
+
this._up0.copy( this.object.up );
|
|
2371
|
+
|
|
2372
|
+
if ( this.object.isPerspectiveCamera ) {
|
|
2373
|
+
|
|
2374
|
+
this._fov0 = this.object.fov;
|
|
2375
|
+
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
/**
|
|
2381
|
+
* Performs uniform scale operation around a given point.
|
|
2382
|
+
*
|
|
2383
|
+
* @private
|
|
2384
|
+
* @param {number} size - Scale factor.
|
|
2385
|
+
* @param {Vector3} point - Point around which scale.
|
|
2386
|
+
* @param {boolean} scaleGizmos - If gizmos should be scaled (Perspective only).
|
|
2387
|
+
* @returns {Object} Object with 'camera' and 'gizmo' fields containing transformation matrices resulting from the operation to be applied to the camera and gizmos.
|
|
2388
|
+
*/
|
|
2389
|
+
scale( size, point, scaleGizmos = true ) {
|
|
2390
|
+
|
|
2391
|
+
_scalePointTemp.copy( point );
|
|
2392
|
+
let sizeInverse = 1 / size;
|
|
2393
|
+
|
|
2394
|
+
if ( this.object.isOrthographicCamera ) {
|
|
2395
|
+
|
|
2396
|
+
//camera zoom
|
|
2397
|
+
this.object.zoom = this._zoomState;
|
|
2398
|
+
this.object.zoom *= size;
|
|
2399
|
+
|
|
2400
|
+
//check min and max zoom
|
|
2401
|
+
if ( this.object.zoom > this.maxZoom ) {
|
|
2402
|
+
|
|
2403
|
+
this.object.zoom = this.maxZoom;
|
|
2404
|
+
sizeInverse = this._zoomState / this.maxZoom;
|
|
2405
|
+
|
|
2406
|
+
} else if ( this.object.zoom < this.minZoom ) {
|
|
2407
|
+
|
|
2408
|
+
this.object.zoom = this.minZoom;
|
|
2409
|
+
sizeInverse = this._zoomState / this.minZoom;
|
|
2410
|
+
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
this.object.updateProjectionMatrix();
|
|
2414
|
+
|
|
2415
|
+
this._v3_1.setFromMatrixPosition( this._gizmoMatrixState ); //gizmos position
|
|
2416
|
+
|
|
2417
|
+
//scale gizmos so they appear in the same spot having the same dimension
|
|
2418
|
+
this._scaleMatrix.makeScale( sizeInverse, sizeInverse, sizeInverse );
|
|
2419
|
+
this._translationMatrix.makeTranslation( - this._v3_1.x, - this._v3_1.y, - this._v3_1.z );
|
|
2420
|
+
|
|
2421
|
+
this._m4_2.makeTranslation( this._v3_1.x, this._v3_1.y, this._v3_1.z ).multiply( this._scaleMatrix );
|
|
2422
|
+
this._m4_2.multiply( this._translationMatrix );
|
|
2423
|
+
|
|
2424
|
+
|
|
2425
|
+
//move camera and gizmos to obtain pinch effect
|
|
2426
|
+
_scalePointTemp.sub( this._v3_1 );
|
|
2427
|
+
|
|
2428
|
+
const amount = _scalePointTemp.clone().multiplyScalar( sizeInverse );
|
|
2429
|
+
_scalePointTemp.sub( amount );
|
|
2430
|
+
|
|
2431
|
+
this._m4_1.makeTranslation( _scalePointTemp.x, _scalePointTemp.y, _scalePointTemp.z );
|
|
2432
|
+
this._m4_2.premultiply( this._m4_1 );
|
|
2433
|
+
|
|
2434
|
+
this.setTransformationMatrices( this._m4_1, this._m4_2 );
|
|
2435
|
+
return _transformation;
|
|
2436
|
+
|
|
2437
|
+
} else if ( this.object.isPerspectiveCamera ) {
|
|
2438
|
+
|
|
2439
|
+
this._v3_1.setFromMatrixPosition( this._cameraMatrixState );
|
|
2440
|
+
this._v3_2.setFromMatrixPosition( this._gizmoMatrixState );
|
|
2441
|
+
|
|
2442
|
+
//move camera
|
|
2443
|
+
let distance = this._v3_1.distanceTo( _scalePointTemp );
|
|
2444
|
+
let amount = distance - ( distance * sizeInverse );
|
|
2445
|
+
|
|
2446
|
+
//check min and max distance
|
|
2447
|
+
const newDistance = distance - amount;
|
|
2448
|
+
if ( newDistance < this.minDistance ) {
|
|
2449
|
+
|
|
2450
|
+
sizeInverse = this.minDistance / distance;
|
|
2451
|
+
amount = distance - ( distance * sizeInverse );
|
|
2452
|
+
|
|
2453
|
+
} else if ( newDistance > this.maxDistance ) {
|
|
2454
|
+
|
|
2455
|
+
sizeInverse = this.maxDistance / distance;
|
|
2456
|
+
amount = distance - ( distance * sizeInverse );
|
|
2457
|
+
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
_offset.copy( _scalePointTemp ).sub( this._v3_1 ).normalize().multiplyScalar( amount );
|
|
2461
|
+
|
|
2462
|
+
this._m4_1.makeTranslation( _offset.x, _offset.y, _offset.z );
|
|
2463
|
+
|
|
2464
|
+
|
|
2465
|
+
if ( scaleGizmos ) {
|
|
2466
|
+
|
|
2467
|
+
//scale gizmos so they appear in the same spot having the same dimension
|
|
2468
|
+
const pos = this._v3_2;
|
|
2469
|
+
|
|
2470
|
+
distance = pos.distanceTo( _scalePointTemp );
|
|
2471
|
+
amount = distance - ( distance * sizeInverse );
|
|
2472
|
+
_offset.copy( _scalePointTemp ).sub( this._v3_2 ).normalize().multiplyScalar( amount );
|
|
2473
|
+
|
|
2474
|
+
this._translationMatrix.makeTranslation( pos.x, pos.y, pos.z );
|
|
2475
|
+
this._scaleMatrix.makeScale( sizeInverse, sizeInverse, sizeInverse );
|
|
2476
|
+
|
|
2477
|
+
this._m4_2.makeTranslation( _offset.x, _offset.y, _offset.z ).multiply( this._translationMatrix );
|
|
2478
|
+
this._m4_2.multiply( this._scaleMatrix );
|
|
2479
|
+
|
|
2480
|
+
this._translationMatrix.makeTranslation( - pos.x, - pos.y, - pos.z );
|
|
2481
|
+
|
|
2482
|
+
this._m4_2.multiply( this._translationMatrix );
|
|
2483
|
+
this.setTransformationMatrices( this._m4_1, this._m4_2 );
|
|
2484
|
+
|
|
2485
|
+
|
|
2486
|
+
} else {
|
|
2487
|
+
|
|
2488
|
+
this.setTransformationMatrices( this._m4_1 );
|
|
2489
|
+
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
return _transformation;
|
|
2493
|
+
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
/**
|
|
2499
|
+
* Sets camera fov.
|
|
2500
|
+
*
|
|
2501
|
+
* @private
|
|
2502
|
+
* @param {number} value - The FOV to be set.
|
|
2503
|
+
*/
|
|
2504
|
+
setFov( value ) {
|
|
2505
|
+
|
|
2506
|
+
if ( this.object.isPerspectiveCamera ) {
|
|
2507
|
+
|
|
2508
|
+
this.object.fov = MathUtils.clamp( value, this.minFov, this.maxFov );
|
|
2509
|
+
this.object.updateProjectionMatrix();
|
|
2510
|
+
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
/**
|
|
2516
|
+
* Sets values in transformation object.
|
|
2517
|
+
*
|
|
2518
|
+
* @private
|
|
2519
|
+
* @param {?Matrix4} [camera=null] - Transformation to be applied to the camera.
|
|
2520
|
+
* @param {?Matrix4} [gizmos=null] - Transformation to be applied to gizmos.
|
|
2521
|
+
*/
|
|
2522
|
+
setTransformationMatrices( camera = null, gizmos = null ) {
|
|
2523
|
+
|
|
2524
|
+
if ( camera != null ) {
|
|
2525
|
+
|
|
2526
|
+
if ( _transformation.camera != null ) {
|
|
2527
|
+
|
|
2528
|
+
_transformation.camera.copy( camera );
|
|
2529
|
+
|
|
2530
|
+
} else {
|
|
2531
|
+
|
|
2532
|
+
_transformation.camera = camera.clone();
|
|
2533
|
+
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
} else {
|
|
2537
|
+
|
|
2538
|
+
_transformation.camera = null;
|
|
2539
|
+
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2542
|
+
if ( gizmos != null ) {
|
|
2543
|
+
|
|
2544
|
+
if ( _transformation.gizmos != null ) {
|
|
2545
|
+
|
|
2546
|
+
_transformation.gizmos.copy( gizmos );
|
|
2547
|
+
|
|
2548
|
+
} else {
|
|
2549
|
+
|
|
2550
|
+
_transformation.gizmos = gizmos.clone();
|
|
2551
|
+
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
} else {
|
|
2555
|
+
|
|
2556
|
+
_transformation.gizmos = null;
|
|
2557
|
+
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
/**
|
|
2563
|
+
* Rotates camera around its direction axis passing by a given point by a given angle.
|
|
2564
|
+
*
|
|
2565
|
+
* @private
|
|
2566
|
+
* @param {Vector3} point - The point where the rotation axis is passing through.
|
|
2567
|
+
* @param {number} angle - Angle in radians.
|
|
2568
|
+
* @returns {Object} The computed transformation matrix.
|
|
2569
|
+
*/
|
|
2570
|
+
zRotate( point, angle ) {
|
|
2571
|
+
|
|
2572
|
+
this._rotationMatrix.makeRotationAxis( this._rotationAxis, angle );
|
|
2573
|
+
this._translationMatrix.makeTranslation( - point.x, - point.y, - point.z );
|
|
2574
|
+
|
|
2575
|
+
this._m4_1.makeTranslation( point.x, point.y, point.z );
|
|
2576
|
+
this._m4_1.multiply( this._rotationMatrix );
|
|
2577
|
+
this._m4_1.multiply( this._translationMatrix );
|
|
2578
|
+
|
|
2579
|
+
this._v3_1.setFromMatrixPosition( this._gizmoMatrixState ).sub( point ); //vector from rotation center to gizmos position
|
|
2580
|
+
this._v3_2.copy( this._v3_1 ).applyAxisAngle( this._rotationAxis, angle ); //apply rotation
|
|
2581
|
+
this._v3_2.sub( this._v3_1 );
|
|
2582
|
+
|
|
2583
|
+
this._m4_2.makeTranslation( this._v3_2.x, this._v3_2.y, this._v3_2.z );
|
|
2584
|
+
|
|
2585
|
+
this.setTransformationMatrices( this._m4_1, this._m4_2 );
|
|
2586
|
+
return _transformation;
|
|
2587
|
+
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
/**
|
|
2591
|
+
* Returns the raycaster that is used for user interaction. This object is shared between all
|
|
2592
|
+
* instances of `ArcballControls`.
|
|
2593
|
+
*
|
|
2594
|
+
* @returns {Raycaster} The internal raycaster.
|
|
2595
|
+
*/
|
|
2596
|
+
getRaycaster() {
|
|
2597
|
+
|
|
2598
|
+
return _raycaster;
|
|
2599
|
+
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
|
|
2603
|
+
/**
|
|
2604
|
+
* Unprojects the cursor on the 3D object surface.
|
|
2605
|
+
*
|
|
2606
|
+
* @private
|
|
2607
|
+
* @param {Vector2} cursor - Cursor coordinates in NDC.
|
|
2608
|
+
* @param {Camera} camera - Virtual camera.
|
|
2609
|
+
* @returns {?Vector3} The point of intersection with the model, if exist, null otherwise.
|
|
2610
|
+
*/
|
|
2611
|
+
unprojectOnObj( cursor, camera ) {
|
|
2612
|
+
|
|
2613
|
+
const raycaster = this.getRaycaster();
|
|
2614
|
+
raycaster.near = camera.near;
|
|
2615
|
+
raycaster.far = camera.far;
|
|
2616
|
+
raycaster.setFromCamera( cursor, camera );
|
|
2617
|
+
|
|
2618
|
+
const intersect = raycaster.intersectObjects( this.scene.children, true );
|
|
2619
|
+
|
|
2620
|
+
for ( let i = 0; i < intersect.length; i ++ ) {
|
|
2621
|
+
|
|
2622
|
+
if ( intersect[ i ].object.uuid != this._gizmos.uuid && intersect[ i ].face != null ) {
|
|
2623
|
+
|
|
2624
|
+
return intersect[ i ].point.clone();
|
|
2625
|
+
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2630
|
+
return null;
|
|
2631
|
+
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
/**
|
|
2635
|
+
* Unproject the cursor on the trackball surface.
|
|
2636
|
+
*
|
|
2637
|
+
* @private
|
|
2638
|
+
* @param {Camera} camera - The virtual camera.
|
|
2639
|
+
* @param {number} cursorX - Cursor horizontal coordinate on screen.
|
|
2640
|
+
* @param {number} cursorY - Cursor vertical coordinate on screen.
|
|
2641
|
+
* @param {HTMLElement} canvas - The canvas where the renderer draws its output.
|
|
2642
|
+
* @param {number} tbRadius - The trackball radius.
|
|
2643
|
+
* @returns {Vector3} The unprojected point on the trackball surface.
|
|
2644
|
+
*/
|
|
2645
|
+
unprojectOnTbSurface( camera, cursorX, cursorY, canvas, tbRadius ) {
|
|
2646
|
+
|
|
2647
|
+
if ( camera.type == 'OrthographicCamera' ) {
|
|
2648
|
+
|
|
2649
|
+
this._v2_1.copy( this.getCursorPosition( cursorX, cursorY, canvas ) );
|
|
2650
|
+
this._v3_1.set( this._v2_1.x, this._v2_1.y, 0 );
|
|
2651
|
+
|
|
2652
|
+
const x2 = Math.pow( this._v2_1.x, 2 );
|
|
2653
|
+
const y2 = Math.pow( this._v2_1.y, 2 );
|
|
2654
|
+
const r2 = Math.pow( this._tbRadius, 2 );
|
|
2655
|
+
|
|
2656
|
+
if ( x2 + y2 <= r2 * 0.5 ) {
|
|
2657
|
+
|
|
2658
|
+
//intersection with sphere
|
|
2659
|
+
this._v3_1.setZ( Math.sqrt( r2 - ( x2 + y2 ) ) );
|
|
2660
|
+
|
|
2661
|
+
} else {
|
|
2662
|
+
|
|
2663
|
+
//intersection with hyperboloid
|
|
2664
|
+
this._v3_1.setZ( ( r2 * 0.5 ) / ( Math.sqrt( x2 + y2 ) ) );
|
|
2665
|
+
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
return this._v3_1;
|
|
2669
|
+
|
|
2670
|
+
} else if ( camera.type == 'PerspectiveCamera' ) {
|
|
2671
|
+
|
|
2672
|
+
//unproject cursor on the near plane
|
|
2673
|
+
this._v2_1.copy( this.getCursorNDC( cursorX, cursorY, canvas ) );
|
|
2674
|
+
|
|
2675
|
+
this._v3_1.set( this._v2_1.x, this._v2_1.y, - 1 );
|
|
2676
|
+
this._v3_1.applyMatrix4( camera.projectionMatrixInverse );
|
|
2677
|
+
|
|
2678
|
+
const rayDir = this._v3_1.clone().normalize(); //unprojected ray direction
|
|
2679
|
+
const cameraGizmoDistance = camera.position.distanceTo( this._gizmos.position );
|
|
2680
|
+
const radius2 = Math.pow( tbRadius, 2 );
|
|
2681
|
+
|
|
2682
|
+
// camera
|
|
2683
|
+
// |\
|
|
2684
|
+
// | \
|
|
2685
|
+
// | \
|
|
2686
|
+
// h | \
|
|
2687
|
+
// | \
|
|
2688
|
+
// | \
|
|
2689
|
+
// _ _ | _ _ _\ _ _ near plane
|
|
2690
|
+
// l
|
|
2691
|
+
|
|
2692
|
+
const h = this._v3_1.z;
|
|
2693
|
+
const l = Math.sqrt( Math.pow( this._v3_1.x, 2 ) + Math.pow( this._v3_1.y, 2 ) );
|
|
2694
|
+
|
|
2695
|
+
if ( l == 0 ) {
|
|
2696
|
+
|
|
2697
|
+
//ray aligned with camera
|
|
2698
|
+
rayDir.set( this._v3_1.x, this._v3_1.y, tbRadius );
|
|
2699
|
+
return rayDir;
|
|
2700
|
+
|
|
2701
|
+
}
|
|
2702
|
+
|
|
2703
|
+
const m = h / l;
|
|
2704
|
+
const q = cameraGizmoDistance;
|
|
2705
|
+
|
|
2706
|
+
/*
|
|
2707
|
+
* calculate intersection point between unprojected ray and trackball surface
|
|
2708
|
+
*|y = m * x + q
|
|
2709
|
+
*|x^2 + y^2 = r^2
|
|
2710
|
+
*
|
|
2711
|
+
* (m^2 + 1) * x^2 + (2 * m * q) * x + q^2 - r^2 = 0
|
|
2712
|
+
*/
|
|
2713
|
+
let a = Math.pow( m, 2 ) + 1;
|
|
2714
|
+
let b = 2 * m * q;
|
|
2715
|
+
let c = Math.pow( q, 2 ) - radius2;
|
|
2716
|
+
let delta = Math.pow( b, 2 ) - ( 4 * a * c );
|
|
2717
|
+
|
|
2718
|
+
if ( delta >= 0 ) {
|
|
2719
|
+
|
|
2720
|
+
//intersection with sphere
|
|
2721
|
+
this._v2_1.setX( ( - b - Math.sqrt( delta ) ) / ( 2 * a ) );
|
|
2722
|
+
this._v2_1.setY( m * this._v2_1.x + q );
|
|
2723
|
+
|
|
2724
|
+
const angle = MathUtils.RAD2DEG * this._v2_1.angle();
|
|
2725
|
+
|
|
2726
|
+
if ( angle >= 45 ) {
|
|
2727
|
+
|
|
2728
|
+
//if angle between intersection point and X' axis is >= 45°, return that point
|
|
2729
|
+
//otherwise, calculate intersection point with hyperboloid
|
|
2730
|
+
|
|
2731
|
+
const rayLength = Math.sqrt( Math.pow( this._v2_1.x, 2 ) + Math.pow( ( cameraGizmoDistance - this._v2_1.y ), 2 ) );
|
|
2732
|
+
rayDir.multiplyScalar( rayLength );
|
|
2733
|
+
rayDir.z += cameraGizmoDistance;
|
|
2734
|
+
return rayDir;
|
|
2735
|
+
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2740
|
+
//intersection with hyperboloid
|
|
2741
|
+
/*
|
|
2742
|
+
*|y = m * x + q
|
|
2743
|
+
*|y = (1 / x) * (r^2 / 2)
|
|
2744
|
+
*
|
|
2745
|
+
* m * x^2 + q * x - r^2 / 2 = 0
|
|
2746
|
+
*/
|
|
2747
|
+
|
|
2748
|
+
a = m;
|
|
2749
|
+
b = q;
|
|
2750
|
+
c = - radius2 * 0.5;
|
|
2751
|
+
delta = Math.pow( b, 2 ) - ( 4 * a * c );
|
|
2752
|
+
this._v2_1.setX( ( - b - Math.sqrt( delta ) ) / ( 2 * a ) );
|
|
2753
|
+
this._v2_1.setY( m * this._v2_1.x + q );
|
|
2754
|
+
|
|
2755
|
+
const rayLength = Math.sqrt( Math.pow( this._v2_1.x, 2 ) + Math.pow( ( cameraGizmoDistance - this._v2_1.y ), 2 ) );
|
|
2756
|
+
|
|
2757
|
+
rayDir.multiplyScalar( rayLength );
|
|
2758
|
+
rayDir.z += cameraGizmoDistance;
|
|
2759
|
+
return rayDir;
|
|
2760
|
+
|
|
2761
|
+
}
|
|
2762
|
+
|
|
2763
|
+
}
|
|
2764
|
+
|
|
2765
|
+
|
|
2766
|
+
/**
|
|
2767
|
+
* Unprojects the cursor on the plane passing through the center of the trackball orthogonal to the camera.
|
|
2768
|
+
*
|
|
2769
|
+
* @private
|
|
2770
|
+
* @param {Camera} camera - The virtual camera.
|
|
2771
|
+
* @param {number} cursorX - Cursor horizontal coordinate on screen.
|
|
2772
|
+
* @param {number} cursorY - Cursor vertical coordinate on screen.
|
|
2773
|
+
* @param {HTMLElement} canvas - The canvas where the renderer draws its output.
|
|
2774
|
+
* @param {boolean} [initialDistance=false] - If initial distance between camera and gizmos should be used for calculations instead of current (Perspective only).
|
|
2775
|
+
* @returns {Vector3} The unprojected point on the trackball plane.
|
|
2776
|
+
*/
|
|
2777
|
+
unprojectOnTbPlane( camera, cursorX, cursorY, canvas, initialDistance = false ) {
|
|
2778
|
+
|
|
2779
|
+
if ( camera.type == 'OrthographicCamera' ) {
|
|
2780
|
+
|
|
2781
|
+
this._v2_1.copy( this.getCursorPosition( cursorX, cursorY, canvas ) );
|
|
2782
|
+
this._v3_1.set( this._v2_1.x, this._v2_1.y, 0 );
|
|
2783
|
+
|
|
2784
|
+
return this._v3_1.clone();
|
|
2785
|
+
|
|
2786
|
+
} else if ( camera.type == 'PerspectiveCamera' ) {
|
|
2787
|
+
|
|
2788
|
+
this._v2_1.copy( this.getCursorNDC( cursorX, cursorY, canvas ) );
|
|
2789
|
+
|
|
2790
|
+
//unproject cursor on the near plane
|
|
2791
|
+
this._v3_1.set( this._v2_1.x, this._v2_1.y, - 1 );
|
|
2792
|
+
this._v3_1.applyMatrix4( camera.projectionMatrixInverse );
|
|
2793
|
+
|
|
2794
|
+
const rayDir = this._v3_1.clone().normalize(); //unprojected ray direction
|
|
2795
|
+
|
|
2796
|
+
// camera
|
|
2797
|
+
// |\
|
|
2798
|
+
// | \
|
|
2799
|
+
// | \
|
|
2800
|
+
// h | \
|
|
2801
|
+
// | \
|
|
2802
|
+
// | \
|
|
2803
|
+
// _ _ | _ _ _\ _ _ near plane
|
|
2804
|
+
// l
|
|
2805
|
+
|
|
2806
|
+
const h = this._v3_1.z;
|
|
2807
|
+
const l = Math.sqrt( Math.pow( this._v3_1.x, 2 ) + Math.pow( this._v3_1.y, 2 ) );
|
|
2808
|
+
let cameraGizmoDistance;
|
|
2809
|
+
|
|
2810
|
+
if ( initialDistance ) {
|
|
2811
|
+
|
|
2812
|
+
cameraGizmoDistance = this._v3_1.setFromMatrixPosition( this._cameraMatrixState0 ).distanceTo( this._v3_2.setFromMatrixPosition( this._gizmoMatrixState0 ) );
|
|
2813
|
+
|
|
2814
|
+
} else {
|
|
2815
|
+
|
|
2816
|
+
cameraGizmoDistance = camera.position.distanceTo( this._gizmos.position );
|
|
2817
|
+
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
/*
|
|
2821
|
+
* calculate intersection point between unprojected ray and the plane
|
|
2822
|
+
*|y = mx + q
|
|
2823
|
+
*|y = 0
|
|
2824
|
+
*
|
|
2825
|
+
* x = -q/m
|
|
2826
|
+
*/
|
|
2827
|
+
if ( l == 0 ) {
|
|
2828
|
+
|
|
2829
|
+
//ray aligned with camera
|
|
2830
|
+
rayDir.set( 0, 0, 0 );
|
|
2831
|
+
return rayDir;
|
|
2832
|
+
|
|
2833
|
+
}
|
|
2834
|
+
|
|
2835
|
+
const m = h / l;
|
|
2836
|
+
const q = cameraGizmoDistance;
|
|
2837
|
+
const x = - q / m;
|
|
2838
|
+
|
|
2839
|
+
const rayLength = Math.sqrt( Math.pow( q, 2 ) + Math.pow( x, 2 ) );
|
|
2840
|
+
rayDir.multiplyScalar( rayLength );
|
|
2841
|
+
rayDir.z = 0;
|
|
2842
|
+
return rayDir;
|
|
2843
|
+
|
|
2844
|
+
}
|
|
2845
|
+
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2848
|
+
/**
|
|
2849
|
+
* Updates camera and gizmos state.
|
|
2850
|
+
*
|
|
2851
|
+
* @private
|
|
2852
|
+
*/
|
|
2853
|
+
updateMatrixState() {
|
|
2854
|
+
|
|
2855
|
+
//update camera and gizmos state
|
|
2856
|
+
this._cameraMatrixState.copy( this.object.matrix );
|
|
2857
|
+
this._gizmoMatrixState.copy( this._gizmos.matrix );
|
|
2858
|
+
|
|
2859
|
+
if ( this.object.isOrthographicCamera ) {
|
|
2860
|
+
|
|
2861
|
+
this._cameraProjectionState.copy( this.object.projectionMatrix );
|
|
2862
|
+
this.object.updateProjectionMatrix();
|
|
2863
|
+
this._zoomState = this.object.zoom;
|
|
2864
|
+
|
|
2865
|
+
} else if ( this.object.isPerspectiveCamera ) {
|
|
2866
|
+
|
|
2867
|
+
this._fovState = this.object.fov;
|
|
2868
|
+
|
|
2869
|
+
}
|
|
2870
|
+
|
|
2871
|
+
}
|
|
2872
|
+
|
|
2873
|
+
/**
|
|
2874
|
+
* Updates the trackball FSA.
|
|
2875
|
+
*
|
|
2876
|
+
* @private
|
|
2877
|
+
* @param {STATE} newState - New state of the FSA.
|
|
2878
|
+
* @param {boolean} updateMatrices - If matrices state should be updated.
|
|
2879
|
+
*/
|
|
2880
|
+
updateTbState( newState, updateMatrices ) {
|
|
2881
|
+
|
|
2882
|
+
this._state = newState;
|
|
2883
|
+
if ( updateMatrices ) {
|
|
2884
|
+
|
|
2885
|
+
this.updateMatrixState();
|
|
2886
|
+
|
|
2887
|
+
}
|
|
2888
|
+
|
|
2889
|
+
}
|
|
2890
|
+
|
|
2891
|
+
update() {
|
|
2892
|
+
|
|
2893
|
+
if ( this.target.equals( this._currentTarget ) === false ) {
|
|
2894
|
+
|
|
2895
|
+
this._gizmos.position.copy( this.target ); //for correct radius calculation
|
|
2896
|
+
this._tbRadius = this.calculateTbRadius( this.object );
|
|
2897
|
+
this.makeGizmos( this.target, this._tbRadius );
|
|
2898
|
+
this._currentTarget.copy( this.target );
|
|
2899
|
+
|
|
2900
|
+
}
|
|
2901
|
+
|
|
2902
|
+
//check min/max parameters
|
|
2903
|
+
if ( this.object.isOrthographicCamera ) {
|
|
2904
|
+
|
|
2905
|
+
//check zoom
|
|
2906
|
+
if ( this.object.zoom > this.maxZoom || this.object.zoom < this.minZoom ) {
|
|
2907
|
+
|
|
2908
|
+
const newZoom = MathUtils.clamp( this.object.zoom, this.minZoom, this.maxZoom );
|
|
2909
|
+
this.applyTransformMatrix( this.scale( newZoom / this.object.zoom, this._gizmos.position, true ) );
|
|
2910
|
+
|
|
2911
|
+
}
|
|
2912
|
+
|
|
2913
|
+
} else if ( this.object.isPerspectiveCamera ) {
|
|
2914
|
+
|
|
2915
|
+
//check distance
|
|
2916
|
+
const distance = this.object.position.distanceTo( this._gizmos.position );
|
|
2917
|
+
|
|
2918
|
+
if ( distance > this.maxDistance + _EPS || distance < this.minDistance - _EPS ) {
|
|
2919
|
+
|
|
2920
|
+
const newDistance = MathUtils.clamp( distance, this.minDistance, this.maxDistance );
|
|
2921
|
+
this.applyTransformMatrix( this.scale( newDistance / distance, this._gizmos.position ) );
|
|
2922
|
+
this.updateMatrixState();
|
|
2923
|
+
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
//check fov
|
|
2927
|
+
if ( this.object.fov < this.minFov || this.object.fov > this.maxFov ) {
|
|
2928
|
+
|
|
2929
|
+
this.object.fov = MathUtils.clamp( this.object.fov, this.minFov, this.maxFov );
|
|
2930
|
+
this.object.updateProjectionMatrix();
|
|
2931
|
+
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
const oldRadius = this._tbRadius;
|
|
2935
|
+
this._tbRadius = this.calculateTbRadius( this.object );
|
|
2936
|
+
|
|
2937
|
+
if ( oldRadius < this._tbRadius - _EPS || oldRadius > this._tbRadius + _EPS ) {
|
|
2938
|
+
|
|
2939
|
+
const scale = ( this._gizmos.scale.x + this._gizmos.scale.y + this._gizmos.scale.z ) / 3;
|
|
2940
|
+
const newRadius = this._tbRadius / scale;
|
|
2941
|
+
const curve = new EllipseCurve( 0, 0, newRadius, newRadius );
|
|
2942
|
+
const points = curve.getPoints( this._curvePts );
|
|
2943
|
+
const curveGeometry = new BufferGeometry().setFromPoints( points );
|
|
2944
|
+
|
|
2945
|
+
for ( const gizmo in this._gizmos.children ) {
|
|
2946
|
+
|
|
2947
|
+
this._gizmos.children[ gizmo ].geometry = curveGeometry;
|
|
2948
|
+
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2951
|
+
}
|
|
2952
|
+
|
|
2953
|
+
}
|
|
2954
|
+
|
|
2955
|
+
this.object.lookAt( this._gizmos.position );
|
|
2956
|
+
|
|
2957
|
+
}
|
|
2958
|
+
|
|
2959
|
+
setStateFromJSON( json ) {
|
|
2960
|
+
|
|
2961
|
+
const state = JSON.parse( json );
|
|
2962
|
+
|
|
2963
|
+
if ( state.arcballState != undefined ) {
|
|
2964
|
+
|
|
2965
|
+
this.target.fromArray( state.arcballState.target );
|
|
2966
|
+
|
|
2967
|
+
this._cameraMatrixState.fromArray( state.arcballState.cameraMatrix.elements );
|
|
2968
|
+
this._cameraMatrixState.decompose( this.object.position, this.object.quaternion, this.object.scale );
|
|
2969
|
+
|
|
2970
|
+
this.object.up.copy( state.arcballState.cameraUp );
|
|
2971
|
+
this.object.near = state.arcballState.cameraNear;
|
|
2972
|
+
this.object.far = state.arcballState.cameraFar;
|
|
2973
|
+
|
|
2974
|
+
this.object.zoom = state.arcballState.cameraZoom;
|
|
2975
|
+
|
|
2976
|
+
if ( this.object.isPerspectiveCamera ) {
|
|
2977
|
+
|
|
2978
|
+
this.object.fov = state.arcballState.cameraFov;
|
|
2979
|
+
|
|
2980
|
+
}
|
|
2981
|
+
|
|
2982
|
+
this._gizmoMatrixState.fromArray( state.arcballState.gizmoMatrix.elements );
|
|
2983
|
+
this._gizmoMatrixState.decompose( this._gizmos.position, this._gizmos.quaternion, this._gizmos.scale );
|
|
2984
|
+
|
|
2985
|
+
this.object.updateMatrix();
|
|
2986
|
+
this.object.updateProjectionMatrix();
|
|
2987
|
+
|
|
2988
|
+
this._gizmos.updateMatrix();
|
|
2989
|
+
|
|
2990
|
+
this._tbRadius = this.calculateTbRadius( this.object );
|
|
2991
|
+
const gizmoTmp = new Matrix4().copy( this._gizmoMatrixState0 );
|
|
2992
|
+
this.makeGizmos( this._gizmos.position, this._tbRadius );
|
|
2993
|
+
this._gizmoMatrixState0.copy( gizmoTmp );
|
|
2994
|
+
|
|
2995
|
+
this.object.lookAt( this._gizmos.position );
|
|
2996
|
+
this.updateTbState( STATE.IDLE, false );
|
|
2997
|
+
|
|
2998
|
+
this.dispatchEvent( _changeEvent );
|
|
2999
|
+
|
|
3000
|
+
}
|
|
3001
|
+
|
|
3002
|
+
}
|
|
3003
|
+
|
|
3004
|
+
}
|
|
3005
|
+
|
|
3006
|
+
//listeners
|
|
3007
|
+
|
|
3008
|
+
function onWindowResize() {
|
|
3009
|
+
|
|
3010
|
+
const scale = ( this._gizmos.scale.x + this._gizmos.scale.y + this._gizmos.scale.z ) / 3;
|
|
3011
|
+
this._tbRadius = this.calculateTbRadius( this.object );
|
|
3012
|
+
|
|
3013
|
+
const newRadius = this._tbRadius / scale;
|
|
3014
|
+
const curve = new EllipseCurve( 0, 0, newRadius, newRadius );
|
|
3015
|
+
const points = curve.getPoints( this._curvePts );
|
|
3016
|
+
const curveGeometry = new BufferGeometry().setFromPoints( points );
|
|
3017
|
+
|
|
3018
|
+
|
|
3019
|
+
for ( const gizmo in this._gizmos.children ) {
|
|
3020
|
+
|
|
3021
|
+
this._gizmos.children[ gizmo ].geometry = curveGeometry;
|
|
3022
|
+
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
this.dispatchEvent( _changeEvent );
|
|
3026
|
+
|
|
3027
|
+
}
|
|
3028
|
+
|
|
3029
|
+
function onContextMenu( event ) {
|
|
3030
|
+
|
|
3031
|
+
if ( ! this.enabled ) {
|
|
3032
|
+
|
|
3033
|
+
return;
|
|
3034
|
+
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
for ( let i = 0; i < this.mouseActions.length; i ++ ) {
|
|
3038
|
+
|
|
3039
|
+
if ( this.mouseActions[ i ].mouse == 2 ) {
|
|
3040
|
+
|
|
3041
|
+
//prevent only if button 2 is actually used
|
|
3042
|
+
event.preventDefault();
|
|
3043
|
+
break;
|
|
3044
|
+
|
|
3045
|
+
}
|
|
3046
|
+
|
|
3047
|
+
}
|
|
3048
|
+
|
|
3049
|
+
}
|
|
3050
|
+
|
|
3051
|
+
function onPointerCancel() {
|
|
3052
|
+
|
|
3053
|
+
this._touchStart.splice( 0, this._touchStart.length );
|
|
3054
|
+
this._touchCurrent.splice( 0, this._touchCurrent.length );
|
|
3055
|
+
this._input = INPUT.NONE;
|
|
3056
|
+
|
|
3057
|
+
}
|
|
3058
|
+
|
|
3059
|
+
function onPointerDown( event ) {
|
|
3060
|
+
|
|
3061
|
+
if ( event.button == 0 && event.isPrimary ) {
|
|
3062
|
+
|
|
3063
|
+
this._downValid = true;
|
|
3064
|
+
this._downEvents.push( event );
|
|
3065
|
+
this._downStart = performance.now();
|
|
3066
|
+
|
|
3067
|
+
} else {
|
|
3068
|
+
|
|
3069
|
+
this._downValid = false;
|
|
3070
|
+
|
|
3071
|
+
}
|
|
3072
|
+
|
|
3073
|
+
if ( event.pointerType == 'touch' && this._input != INPUT.CURSOR ) {
|
|
3074
|
+
|
|
3075
|
+
this._touchStart.push( event );
|
|
3076
|
+
this._touchCurrent.push( event );
|
|
3077
|
+
|
|
3078
|
+
switch ( this._input ) {
|
|
3079
|
+
|
|
3080
|
+
case INPUT.NONE:
|
|
3081
|
+
|
|
3082
|
+
//singleStart
|
|
3083
|
+
this._input = INPUT.ONE_FINGER;
|
|
3084
|
+
this.onSinglePanStart( event, 'ROTATE' );
|
|
3085
|
+
|
|
3086
|
+
window.addEventListener( 'pointermove', this._onPointerMove );
|
|
3087
|
+
window.addEventListener( 'pointerup', this._onPointerUp );
|
|
3088
|
+
|
|
3089
|
+
break;
|
|
3090
|
+
|
|
3091
|
+
case INPUT.ONE_FINGER:
|
|
3092
|
+
case INPUT.ONE_FINGER_SWITCHED:
|
|
3093
|
+
|
|
3094
|
+
//doubleStart
|
|
3095
|
+
this._input = INPUT.TWO_FINGER;
|
|
3096
|
+
|
|
3097
|
+
this.onRotateStart();
|
|
3098
|
+
this.onPinchStart();
|
|
3099
|
+
this.onDoublePanStart();
|
|
3100
|
+
|
|
3101
|
+
break;
|
|
3102
|
+
|
|
3103
|
+
case INPUT.TWO_FINGER:
|
|
3104
|
+
|
|
3105
|
+
//multipleStart
|
|
3106
|
+
this._input = INPUT.MULT_FINGER;
|
|
3107
|
+
this.onTriplePanStart( event );
|
|
3108
|
+
break;
|
|
3109
|
+
|
|
3110
|
+
}
|
|
3111
|
+
|
|
3112
|
+
} else if ( event.pointerType != 'touch' && this._input == INPUT.NONE ) {
|
|
3113
|
+
|
|
3114
|
+
let modifier = null;
|
|
3115
|
+
|
|
3116
|
+
if ( event.ctrlKey || event.metaKey ) {
|
|
3117
|
+
|
|
3118
|
+
modifier = 'CTRL';
|
|
3119
|
+
|
|
3120
|
+
} else if ( event.shiftKey ) {
|
|
3121
|
+
|
|
3122
|
+
modifier = 'SHIFT';
|
|
3123
|
+
|
|
3124
|
+
}
|
|
3125
|
+
|
|
3126
|
+
this._mouseOp = this.getOpFromAction( event.button, modifier );
|
|
3127
|
+
if ( this._mouseOp != null ) {
|
|
3128
|
+
|
|
3129
|
+
window.addEventListener( 'pointermove', this._onPointerMove );
|
|
3130
|
+
window.addEventListener( 'pointerup', this._onPointerUp );
|
|
3131
|
+
|
|
3132
|
+
//singleStart
|
|
3133
|
+
this._input = INPUT.CURSOR;
|
|
3134
|
+
this._button = event.button;
|
|
3135
|
+
this.onSinglePanStart( event, this._mouseOp );
|
|
3136
|
+
|
|
3137
|
+
}
|
|
3138
|
+
|
|
3139
|
+
}
|
|
3140
|
+
|
|
3141
|
+
}
|
|
3142
|
+
|
|
3143
|
+
function onPointerMove( event ) {
|
|
3144
|
+
|
|
3145
|
+
if ( event.pointerType == 'touch' && this._input != INPUT.CURSOR ) {
|
|
3146
|
+
|
|
3147
|
+
switch ( this._input ) {
|
|
3148
|
+
|
|
3149
|
+
case INPUT.ONE_FINGER:
|
|
3150
|
+
|
|
3151
|
+
//singleMove
|
|
3152
|
+
this.updateTouchEvent( event );
|
|
3153
|
+
|
|
3154
|
+
this.onSinglePanMove( event, STATE.ROTATE );
|
|
3155
|
+
break;
|
|
3156
|
+
|
|
3157
|
+
case INPUT.ONE_FINGER_SWITCHED:
|
|
3158
|
+
|
|
3159
|
+
const movement = this.calculatePointersDistance( this._touchCurrent[ 0 ], event ) * this._devPxRatio;
|
|
3160
|
+
|
|
3161
|
+
if ( movement >= this._switchSensibility ) {
|
|
3162
|
+
|
|
3163
|
+
//singleMove
|
|
3164
|
+
this._input = INPUT.ONE_FINGER;
|
|
3165
|
+
this.updateTouchEvent( event );
|
|
3166
|
+
|
|
3167
|
+
this.onSinglePanStart( event, 'ROTATE' );
|
|
3168
|
+
break;
|
|
3169
|
+
|
|
3170
|
+
}
|
|
3171
|
+
|
|
3172
|
+
break;
|
|
3173
|
+
|
|
3174
|
+
case INPUT.TWO_FINGER:
|
|
3175
|
+
|
|
3176
|
+
//rotate/pan/pinchMove
|
|
3177
|
+
this.updateTouchEvent( event );
|
|
3178
|
+
|
|
3179
|
+
this.onRotateMove();
|
|
3180
|
+
this.onPinchMove();
|
|
3181
|
+
this.onDoublePanMove();
|
|
3182
|
+
|
|
3183
|
+
break;
|
|
3184
|
+
|
|
3185
|
+
case INPUT.MULT_FINGER:
|
|
3186
|
+
|
|
3187
|
+
//multMove
|
|
3188
|
+
this.updateTouchEvent( event );
|
|
3189
|
+
|
|
3190
|
+
this.onTriplePanMove( event );
|
|
3191
|
+
break;
|
|
3192
|
+
|
|
3193
|
+
}
|
|
3194
|
+
|
|
3195
|
+
} else if ( event.pointerType != 'touch' && this._input == INPUT.CURSOR ) {
|
|
3196
|
+
|
|
3197
|
+
let modifier = null;
|
|
3198
|
+
|
|
3199
|
+
if ( event.ctrlKey || event.metaKey ) {
|
|
3200
|
+
|
|
3201
|
+
modifier = 'CTRL';
|
|
3202
|
+
|
|
3203
|
+
} else if ( event.shiftKey ) {
|
|
3204
|
+
|
|
3205
|
+
modifier = 'SHIFT';
|
|
3206
|
+
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
const mouseOpState = this.getOpStateFromAction( this._button, modifier );
|
|
3210
|
+
|
|
3211
|
+
if ( mouseOpState != null ) {
|
|
3212
|
+
|
|
3213
|
+
this.onSinglePanMove( event, mouseOpState );
|
|
3214
|
+
|
|
3215
|
+
}
|
|
3216
|
+
|
|
3217
|
+
}
|
|
3218
|
+
|
|
3219
|
+
//checkDistance
|
|
3220
|
+
if ( this._downValid ) {
|
|
3221
|
+
|
|
3222
|
+
const movement = this.calculatePointersDistance( this._downEvents[ this._downEvents.length - 1 ], event ) * this._devPxRatio;
|
|
3223
|
+
if ( movement > this._movementThreshold ) {
|
|
3224
|
+
|
|
3225
|
+
this._downValid = false;
|
|
3226
|
+
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3229
|
+
}
|
|
3230
|
+
|
|
3231
|
+
}
|
|
3232
|
+
|
|
3233
|
+
function onPointerUp( event ) {
|
|
3234
|
+
|
|
3235
|
+
if ( event.pointerType == 'touch' && this._input != INPUT.CURSOR ) {
|
|
3236
|
+
|
|
3237
|
+
const nTouch = this._touchCurrent.length;
|
|
3238
|
+
|
|
3239
|
+
for ( let i = 0; i < nTouch; i ++ ) {
|
|
3240
|
+
|
|
3241
|
+
if ( this._touchCurrent[ i ].pointerId == event.pointerId ) {
|
|
3242
|
+
|
|
3243
|
+
this._touchCurrent.splice( i, 1 );
|
|
3244
|
+
this._touchStart.splice( i, 1 );
|
|
3245
|
+
break;
|
|
3246
|
+
|
|
3247
|
+
}
|
|
3248
|
+
|
|
3249
|
+
}
|
|
3250
|
+
|
|
3251
|
+
switch ( this._input ) {
|
|
3252
|
+
|
|
3253
|
+
case INPUT.ONE_FINGER:
|
|
3254
|
+
case INPUT.ONE_FINGER_SWITCHED:
|
|
3255
|
+
|
|
3256
|
+
//singleEnd
|
|
3257
|
+
window.removeEventListener( 'pointermove', this._onPointerMove );
|
|
3258
|
+
window.removeEventListener( 'pointerup', this._onPointerUp );
|
|
3259
|
+
|
|
3260
|
+
this._input = INPUT.NONE;
|
|
3261
|
+
this.onSinglePanEnd();
|
|
3262
|
+
|
|
3263
|
+
break;
|
|
3264
|
+
|
|
3265
|
+
case INPUT.TWO_FINGER:
|
|
3266
|
+
|
|
3267
|
+
//doubleEnd
|
|
3268
|
+
this.onDoublePanEnd( event );
|
|
3269
|
+
this.onPinchEnd( event );
|
|
3270
|
+
this.onRotateEnd( event );
|
|
3271
|
+
|
|
3272
|
+
//switching to singleStart
|
|
3273
|
+
this._input = INPUT.ONE_FINGER_SWITCHED;
|
|
3274
|
+
|
|
3275
|
+
break;
|
|
3276
|
+
|
|
3277
|
+
case INPUT.MULT_FINGER:
|
|
3278
|
+
|
|
3279
|
+
if ( this._touchCurrent.length == 0 ) {
|
|
3280
|
+
|
|
3281
|
+
window.removeEventListener( 'pointermove', this._onPointerMove );
|
|
3282
|
+
window.removeEventListener( 'pointerup', this._onPointerUp );
|
|
3283
|
+
|
|
3284
|
+
//multCancel
|
|
3285
|
+
this._input = INPUT.NONE;
|
|
3286
|
+
this.onTriplePanEnd();
|
|
3287
|
+
|
|
3288
|
+
}
|
|
3289
|
+
|
|
3290
|
+
break;
|
|
3291
|
+
|
|
3292
|
+
}
|
|
3293
|
+
|
|
3294
|
+
} else if ( event.pointerType != 'touch' && this._input == INPUT.CURSOR ) {
|
|
3295
|
+
|
|
3296
|
+
window.removeEventListener( 'pointermove', this._onPointerMove );
|
|
3297
|
+
window.removeEventListener( 'pointerup', this._onPointerUp );
|
|
3298
|
+
|
|
3299
|
+
this._input = INPUT.NONE;
|
|
3300
|
+
this.onSinglePanEnd();
|
|
3301
|
+
this._button = - 1;
|
|
3302
|
+
|
|
3303
|
+
}
|
|
3304
|
+
|
|
3305
|
+
if ( event.isPrimary ) {
|
|
3306
|
+
|
|
3307
|
+
if ( this._downValid ) {
|
|
3308
|
+
|
|
3309
|
+
const downTime = event.timeStamp - this._downEvents[ this._downEvents.length - 1 ].timeStamp;
|
|
3310
|
+
|
|
3311
|
+
if ( downTime <= this._maxDownTime ) {
|
|
3312
|
+
|
|
3313
|
+
if ( this._nclicks == 0 ) {
|
|
3314
|
+
|
|
3315
|
+
//first valid click detected
|
|
3316
|
+
this._nclicks = 1;
|
|
3317
|
+
this._clickStart = performance.now();
|
|
3318
|
+
|
|
3319
|
+
} else {
|
|
3320
|
+
|
|
3321
|
+
const clickInterval = event.timeStamp - this._clickStart;
|
|
3322
|
+
const movement = this.calculatePointersDistance( this._downEvents[ 1 ], this._downEvents[ 0 ] ) * this._devPxRatio;
|
|
3323
|
+
|
|
3324
|
+
if ( clickInterval <= this._maxInterval && movement <= this._posThreshold ) {
|
|
3325
|
+
|
|
3326
|
+
//second valid click detected
|
|
3327
|
+
//fire double tap and reset values
|
|
3328
|
+
this._nclicks = 0;
|
|
3329
|
+
this._downEvents.splice( 0, this._downEvents.length );
|
|
3330
|
+
this.onDoubleTap( event );
|
|
3331
|
+
|
|
3332
|
+
} else {
|
|
3333
|
+
|
|
3334
|
+
//new 'first click'
|
|
3335
|
+
this._nclicks = 1;
|
|
3336
|
+
this._downEvents.shift();
|
|
3337
|
+
this._clickStart = performance.now();
|
|
3338
|
+
|
|
3339
|
+
}
|
|
3340
|
+
|
|
3341
|
+
}
|
|
3342
|
+
|
|
3343
|
+
} else {
|
|
3344
|
+
|
|
3345
|
+
this._downValid = false;
|
|
3346
|
+
this._nclicks = 0;
|
|
3347
|
+
this._downEvents.splice( 0, this._downEvents.length );
|
|
3348
|
+
|
|
3349
|
+
}
|
|
3350
|
+
|
|
3351
|
+
} else {
|
|
3352
|
+
|
|
3353
|
+
this._nclicks = 0;
|
|
3354
|
+
this._downEvents.splice( 0, this._downEvents.length );
|
|
3355
|
+
|
|
3356
|
+
}
|
|
3357
|
+
|
|
3358
|
+
}
|
|
3359
|
+
|
|
3360
|
+
}
|
|
3361
|
+
|
|
3362
|
+
function onWheel( event ) {
|
|
3363
|
+
|
|
3364
|
+
if ( this.enabled && this.enableZoom ) {
|
|
3365
|
+
|
|
3366
|
+
let modifier = null;
|
|
3367
|
+
|
|
3368
|
+
if ( event.ctrlKey || event.metaKey ) {
|
|
3369
|
+
|
|
3370
|
+
modifier = 'CTRL';
|
|
3371
|
+
|
|
3372
|
+
} else if ( event.shiftKey ) {
|
|
3373
|
+
|
|
3374
|
+
modifier = 'SHIFT';
|
|
3375
|
+
|
|
3376
|
+
}
|
|
3377
|
+
|
|
3378
|
+
const mouseOp = this.getOpFromAction( 'WHEEL', modifier );
|
|
3379
|
+
|
|
3380
|
+
if ( mouseOp != null ) {
|
|
3381
|
+
|
|
3382
|
+
event.preventDefault();
|
|
3383
|
+
this.dispatchEvent( _startEvent );
|
|
3384
|
+
|
|
3385
|
+
const notchDeltaY = 125; //distance of one notch of mouse wheel
|
|
3386
|
+
let sgn = event.deltaY / notchDeltaY;
|
|
3387
|
+
|
|
3388
|
+
let size = 1;
|
|
3389
|
+
|
|
3390
|
+
if ( sgn > 0 ) {
|
|
3391
|
+
|
|
3392
|
+
size = 1 / this.scaleFactor;
|
|
3393
|
+
|
|
3394
|
+
} else if ( sgn < 0 ) {
|
|
3395
|
+
|
|
3396
|
+
size = this.scaleFactor;
|
|
3397
|
+
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
switch ( mouseOp ) {
|
|
3401
|
+
|
|
3402
|
+
case 'ZOOM':
|
|
3403
|
+
|
|
3404
|
+
this.updateTbState( STATE.SCALE, true );
|
|
3405
|
+
|
|
3406
|
+
if ( sgn > 0 ) {
|
|
3407
|
+
|
|
3408
|
+
size = 1 / ( Math.pow( this.scaleFactor, sgn ) );
|
|
3409
|
+
|
|
3410
|
+
} else if ( sgn < 0 ) {
|
|
3411
|
+
|
|
3412
|
+
size = Math.pow( this.scaleFactor, - sgn );
|
|
3413
|
+
|
|
3414
|
+
}
|
|
3415
|
+
|
|
3416
|
+
if ( this.cursorZoom && this.enablePan ) {
|
|
3417
|
+
|
|
3418
|
+
let scalePoint;
|
|
3419
|
+
|
|
3420
|
+
if ( this.object.isOrthographicCamera ) {
|
|
3421
|
+
|
|
3422
|
+
scalePoint = this.unprojectOnTbPlane( this.object, event.clientX, event.clientY, this.domElement ).applyQuaternion( this.object.quaternion ).multiplyScalar( 1 / this.object.zoom ).add( this._gizmos.position );
|
|
3423
|
+
|
|
3424
|
+
} else if ( this.object.isPerspectiveCamera ) {
|
|
3425
|
+
|
|
3426
|
+
scalePoint = this.unprojectOnTbPlane( this.object, event.clientX, event.clientY, this.domElement ).applyQuaternion( this.object.quaternion ).add( this._gizmos.position );
|
|
3427
|
+
|
|
3428
|
+
}
|
|
3429
|
+
|
|
3430
|
+
this.applyTransformMatrix( this.scale( size, scalePoint ) );
|
|
3431
|
+
|
|
3432
|
+
} else {
|
|
3433
|
+
|
|
3434
|
+
this.applyTransformMatrix( this.scale( size, this._gizmos.position ) );
|
|
3435
|
+
|
|
3436
|
+
}
|
|
3437
|
+
|
|
3438
|
+
if ( this._grid != null ) {
|
|
3439
|
+
|
|
3440
|
+
this.disposeGrid();
|
|
3441
|
+
this.drawGrid();
|
|
3442
|
+
|
|
3443
|
+
}
|
|
3444
|
+
|
|
3445
|
+
this.updateTbState( STATE.IDLE, false );
|
|
3446
|
+
|
|
3447
|
+
this.dispatchEvent( _changeEvent );
|
|
3448
|
+
this.dispatchEvent( _endEvent );
|
|
3449
|
+
|
|
3450
|
+
break;
|
|
3451
|
+
|
|
3452
|
+
case 'FOV':
|
|
3453
|
+
|
|
3454
|
+
if ( this.object.isPerspectiveCamera ) {
|
|
3455
|
+
|
|
3456
|
+
this.updateTbState( STATE.FOV, true );
|
|
3457
|
+
|
|
3458
|
+
|
|
3459
|
+
//Vertigo effect
|
|
3460
|
+
|
|
3461
|
+
// fov / 2
|
|
3462
|
+
// |\
|
|
3463
|
+
// | \
|
|
3464
|
+
// | \
|
|
3465
|
+
// x | \
|
|
3466
|
+
// | \
|
|
3467
|
+
// | \
|
|
3468
|
+
// | _ _ _\
|
|
3469
|
+
// y
|
|
3470
|
+
|
|
3471
|
+
//check for iOs shift shortcut
|
|
3472
|
+
if ( event.deltaX != 0 ) {
|
|
3473
|
+
|
|
3474
|
+
sgn = event.deltaX / notchDeltaY;
|
|
3475
|
+
|
|
3476
|
+
size = 1;
|
|
3477
|
+
|
|
3478
|
+
if ( sgn > 0 ) {
|
|
3479
|
+
|
|
3480
|
+
size = 1 / ( Math.pow( this.scaleFactor, sgn ) );
|
|
3481
|
+
|
|
3482
|
+
} else if ( sgn < 0 ) {
|
|
3483
|
+
|
|
3484
|
+
size = Math.pow( this.scaleFactor, - sgn );
|
|
3485
|
+
|
|
3486
|
+
}
|
|
3487
|
+
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3490
|
+
this._v3_1.setFromMatrixPosition( this._cameraMatrixState );
|
|
3491
|
+
const x = this._v3_1.distanceTo( this._gizmos.position );
|
|
3492
|
+
let xNew = x / size; //distance between camera and gizmos if scale(size, scalepoint) would be performed
|
|
3493
|
+
|
|
3494
|
+
//check min and max distance
|
|
3495
|
+
xNew = MathUtils.clamp( xNew, this.minDistance, this.maxDistance );
|
|
3496
|
+
|
|
3497
|
+
const y = x * Math.tan( MathUtils.DEG2RAD * this.object.fov * 0.5 );
|
|
3498
|
+
|
|
3499
|
+
//calculate new fov
|
|
3500
|
+
let newFov = MathUtils.RAD2DEG * ( Math.atan( y / xNew ) * 2 );
|
|
3501
|
+
|
|
3502
|
+
//check min and max fov
|
|
3503
|
+
if ( newFov > this.maxFov ) {
|
|
3504
|
+
|
|
3505
|
+
newFov = this.maxFov;
|
|
3506
|
+
|
|
3507
|
+
} else if ( newFov < this.minFov ) {
|
|
3508
|
+
|
|
3509
|
+
newFov = this.minFov;
|
|
3510
|
+
|
|
3511
|
+
}
|
|
3512
|
+
|
|
3513
|
+
const newDistance = y / Math.tan( MathUtils.DEG2RAD * ( newFov / 2 ) );
|
|
3514
|
+
size = x / newDistance;
|
|
3515
|
+
|
|
3516
|
+
this.setFov( newFov );
|
|
3517
|
+
this.applyTransformMatrix( this.scale( size, this._gizmos.position, false ) );
|
|
3518
|
+
|
|
3519
|
+
}
|
|
3520
|
+
|
|
3521
|
+
if ( this._grid != null ) {
|
|
3522
|
+
|
|
3523
|
+
this.disposeGrid();
|
|
3524
|
+
this.drawGrid();
|
|
3525
|
+
|
|
3526
|
+
}
|
|
3527
|
+
|
|
3528
|
+
this.updateTbState( STATE.IDLE, false );
|
|
3529
|
+
|
|
3530
|
+
this.dispatchEvent( _changeEvent );
|
|
3531
|
+
this.dispatchEvent( _endEvent );
|
|
3532
|
+
|
|
3533
|
+
break;
|
|
3534
|
+
|
|
3535
|
+
}
|
|
3536
|
+
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
}
|
|
3540
|
+
|
|
3541
|
+
}
|
|
3542
|
+
|
|
3543
|
+
export { ArcballControls };
|