itowns 2.44.3-next.8 → 2.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -129
- package/examples/3dtiles_loader.html +123 -48
- package/examples/config.json +3 -10
- package/examples/copc_simple_loader.html +15 -5
- package/examples/effects_stereo.html +2 -2
- package/examples/entwine_3d_loader.html +3 -1
- package/examples/entwine_simple_loader.html +1 -1
- package/examples/images/itowns_logo.svg +123 -0
- package/examples/js/plugins/COGParser.js +1 -1
- package/examples/jsm/OGC3DTilesHelper.js +6 -1
- package/examples/layers/JSONLayers/GeoidMNT.json +3 -1
- package/examples/misc_collada.html +2 -2
- package/examples/source_file_geojson_3d.html +0 -1
- package/examples/source_file_kml_raster_usgs.html +0 -1
- package/examples/source_stream_wfs_raster.html +0 -7
- package/examples/vector_tile_mapbox_raster.html +91 -0
- package/examples/view_3d_map_webxr.html +3 -1
- package/examples/view_multi_25d.html +2 -2
- package/package.json +21 -75
- package/CODING.md +0 -120
- package/CONTRIBUTING.md +0 -150
- package/CONTRIBUTORS.md +0 -55
- package/LICENSE.md +0 -44
- package/changelog.md +0 -1361
- package/dist/455.js +0 -2
- package/dist/455.js.map +0 -1
- package/dist/debug.js +0 -3
- package/dist/debug.js.LICENSE.txt +0 -13
- package/dist/debug.js.map +0 -1
- package/dist/itowns.js +0 -3
- package/dist/itowns.js.LICENSE.txt +0 -7
- package/dist/itowns.js.map +0 -1
- package/dist/itowns_lasparser.js +0 -2
- package/dist/itowns_lasparser.js.map +0 -1
- package/dist/itowns_lasworker.js +0 -2
- package/dist/itowns_lasworker.js.map +0 -1
- package/dist/itowns_potree2worker.js +0 -2
- package/dist/itowns_potree2worker.js.map +0 -1
- package/dist/itowns_widgets.js +0 -2
- package/dist/itowns_widgets.js.map +0 -1
- package/examples/.eslintrc.cjs +0 -35
- package/examples/3dtiles_25d.html +0 -120
- package/examples/3dtiles_basic.html +0 -94
- package/examples/3dtiles_batch_table.html +0 -86
- package/examples/3dtiles_ion.html +0 -126
- package/examples/3dtiles_pointcloud.html +0 -95
- package/examples/jsm/.eslintrc.cjs +0 -38
- package/lib/Controls/FirstPersonControls.js +0 -308
- package/lib/Controls/FlyControls.js +0 -175
- package/lib/Controls/GlobeControls.js +0 -1162
- package/lib/Controls/PlanarControls.js +0 -1025
- package/lib/Controls/StateControl.js +0 -429
- package/lib/Controls/StreetControls.js +0 -392
- package/lib/Converter/Feature2Mesh.js +0 -615
- package/lib/Converter/Feature2Texture.js +0 -170
- package/lib/Converter/convertToTile.js +0 -75
- package/lib/Converter/textureConverter.js +0 -44
- package/lib/Core/3DTiles/C3DTBatchTable.js +0 -131
- package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +0 -96
- package/lib/Core/3DTiles/C3DTBoundingVolume.js +0 -157
- package/lib/Core/3DTiles/C3DTExtensions.js +0 -97
- package/lib/Core/3DTiles/C3DTFeature.js +0 -110
- package/lib/Core/3DTiles/C3DTilesEnums.js +0 -20
- package/lib/Core/3DTiles/C3DTileset.js +0 -99
- package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +0 -100
- package/lib/Core/AnimationPlayer.js +0 -142
- package/lib/Core/CopcNode.js +0 -174
- package/lib/Core/Deprecated/Undeprecator.js +0 -75
- package/lib/Core/EntwinePointTileNode.js +0 -126
- package/lib/Core/Feature.js +0 -490
- package/lib/Core/Geographic/CoordStars.js +0 -80
- package/lib/Core/Geographic/Coordinates.js +0 -320
- package/lib/Core/Geographic/Crs.js +0 -175
- package/lib/Core/Geographic/Extent.js +0 -534
- package/lib/Core/Geographic/GeoidGrid.js +0 -109
- package/lib/Core/Label.js +0 -222
- package/lib/Core/MainLoop.js +0 -211
- package/lib/Core/Math/Ellipsoid.js +0 -144
- package/lib/Core/Picking.js +0 -255
- package/lib/Core/PointCloudNode.js +0 -42
- package/lib/Core/Potree2Node.js +0 -206
- package/lib/Core/Potree2PointAttributes.js +0 -139
- package/lib/Core/PotreeNode.js +0 -101
- package/lib/Core/Prefab/Globe/Atmosphere.js +0 -299
- package/lib/Core/Prefab/Globe/BuilderEllipsoidTile.js +0 -110
- package/lib/Core/Prefab/Globe/GlobeLayer.js +0 -145
- package/lib/Core/Prefab/Globe/SkyShader.js +0 -78
- package/lib/Core/Prefab/GlobeView.js +0 -161
- package/lib/Core/Prefab/Planar/PlanarLayer.js +0 -53
- package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +0 -72
- package/lib/Core/Prefab/PlanarView.js +0 -62
- package/lib/Core/Prefab/TileBuilder.js +0 -80
- package/lib/Core/Prefab/computeBufferTileGeometry.js +0 -183
- package/lib/Core/Scheduler/Cache.js +0 -256
- package/lib/Core/Scheduler/CancelledCommandException.js +0 -15
- package/lib/Core/Scheduler/Scheduler.js +0 -294
- package/lib/Core/Style.js +0 -1121
- package/lib/Core/System/Capabilities.js +0 -63
- package/lib/Core/Tile/Tile.js +0 -219
- package/lib/Core/Tile/TileGrid.js +0 -46
- package/lib/Core/TileGeometry.js +0 -40
- package/lib/Core/TileMesh.js +0 -109
- package/lib/Core/View.js +0 -1109
- package/lib/Layer/C3DTilesLayer.js +0 -455
- package/lib/Layer/ColorLayer.js +0 -128
- package/lib/Layer/CopcLayer.js +0 -58
- package/lib/Layer/ElevationLayer.js +0 -107
- package/lib/Layer/EntwinePointTileLayer.js +0 -64
- package/lib/Layer/FeatureGeometryLayer.js +0 -63
- package/lib/Layer/GeoidLayer.js +0 -80
- package/lib/Layer/GeometryLayer.js +0 -202
- package/lib/Layer/InfoLayer.js +0 -64
- package/lib/Layer/LabelLayer.js +0 -456
- package/lib/Layer/Layer.js +0 -304
- package/lib/Layer/LayerUpdateState.js +0 -89
- package/lib/Layer/LayerUpdateStrategy.js +0 -80
- package/lib/Layer/OGC3DTilesLayer.js +0 -387
- package/lib/Layer/OrientedImageLayer.js +0 -222
- package/lib/Layer/PointCloudLayer.js +0 -359
- package/lib/Layer/Potree2Layer.js +0 -164
- package/lib/Layer/PotreeLayer.js +0 -65
- package/lib/Layer/RasterLayer.js +0 -27
- package/lib/Layer/ReferencingLayerProperties.js +0 -62
- package/lib/Layer/TiledGeometryLayer.js +0 -403
- package/lib/Loader/LASLoader.js +0 -193
- package/lib/Loader/Potree2BrotliLoader.js +0 -261
- package/lib/Loader/Potree2Loader.js +0 -207
- package/lib/Main.js +0 -115
- package/lib/MainBundle.js +0 -4
- package/lib/Parser/B3dmParser.js +0 -174
- package/lib/Parser/CameraCalibrationParser.js +0 -94
- package/lib/Parser/GDFParser.js +0 -72
- package/lib/Parser/GTXParser.js +0 -75
- package/lib/Parser/GeoJsonParser.js +0 -212
- package/lib/Parser/GpxParser.js +0 -25
- package/lib/Parser/ISGParser.js +0 -71
- package/lib/Parser/KMLParser.js +0 -25
- package/lib/Parser/LASParser.js +0 -137
- package/lib/Parser/MapBoxUrlParser.js +0 -83
- package/lib/Parser/PntsParser.js +0 -131
- package/lib/Parser/Potree2BinParser.js +0 -92
- package/lib/Parser/PotreeBinParser.js +0 -106
- package/lib/Parser/PotreeCinParser.js +0 -29
- package/lib/Parser/ShapefileParser.js +0 -78
- package/lib/Parser/VectorTileParser.js +0 -202
- package/lib/Parser/XbilParser.js +0 -119
- package/lib/Parser/deprecated/LegacyGLTFLoader.js +0 -1386
- package/lib/Parser/iGLTFLoader.js +0 -168
- package/lib/Process/3dTilesProcessing.js +0 -304
- package/lib/Process/FeatureProcessing.js +0 -76
- package/lib/Process/LayeredMaterialNodeProcessing.js +0 -221
- package/lib/Process/ObjectRemovalHelper.js +0 -97
- package/lib/Process/handlerNodeError.js +0 -23
- package/lib/Provider/3dTilesProvider.js +0 -149
- package/lib/Provider/DataSourceProvider.js +0 -8
- package/lib/Provider/Fetcher.js +0 -229
- package/lib/Provider/PointCloudProvider.js +0 -45
- package/lib/Provider/TileProvider.js +0 -16
- package/lib/Provider/URLBuilder.js +0 -116
- package/lib/Renderer/Camera.js +0 -281
- package/lib/Renderer/Color.js +0 -56
- package/lib/Renderer/ColorLayersOrdering.js +0 -115
- package/lib/Renderer/CommonMaterial.js +0 -31
- package/lib/Renderer/Label2DRenderer.js +0 -190
- package/lib/Renderer/LayeredMaterial.js +0 -243
- package/lib/Renderer/OBB.js +0 -153
- package/lib/Renderer/OrientedImageCamera.js +0 -118
- package/lib/Renderer/OrientedImageMaterial.js +0 -167
- package/lib/Renderer/PointsMaterial.js +0 -485
- package/lib/Renderer/RasterTile.js +0 -209
- package/lib/Renderer/RenderMode.js +0 -31
- package/lib/Renderer/Shader/ShaderChunk.js +0 -160
- package/lib/Renderer/Shader/ShaderUtils.js +0 -47
- package/lib/Renderer/SphereHelper.js +0 -23
- package/lib/Renderer/WebXR.js +0 -51
- package/lib/Renderer/c3DEngine.js +0 -214
- package/lib/Source/C3DTilesGoogleSource.js +0 -74
- package/lib/Source/C3DTilesIonSource.js +0 -54
- package/lib/Source/C3DTilesSource.js +0 -30
- package/lib/Source/CopcSource.js +0 -115
- package/lib/Source/EntwinePointTileSource.js +0 -62
- package/lib/Source/FileSource.js +0 -189
- package/lib/Source/OGC3DTilesGoogleSource.js +0 -29
- package/lib/Source/OGC3DTilesIonSource.js +0 -34
- package/lib/Source/OGC3DTilesSource.js +0 -21
- package/lib/Source/OrientedImageSource.js +0 -59
- package/lib/Source/Potree2Source.js +0 -167
- package/lib/Source/PotreeSource.js +0 -82
- package/lib/Source/Source.js +0 -223
- package/lib/Source/TMSSource.js +0 -145
- package/lib/Source/VectorTilesSource.js +0 -178
- package/lib/Source/WFSSource.js +0 -168
- package/lib/Source/WMSSource.js +0 -133
- package/lib/Source/WMTSSource.js +0 -86
- package/lib/ThreeExtended/capabilities/WebGL.js +0 -69
- package/lib/ThreeExtended/libs/ktx-parse.module.js +0 -470
- package/lib/ThreeExtended/libs/zstddec.module.js +0 -29
- package/lib/ThreeExtended/loaders/DDSLoader.js +0 -200
- package/lib/ThreeExtended/loaders/DRACOLoader.js +0 -399
- package/lib/ThreeExtended/loaders/GLTFLoader.js +0 -2876
- package/lib/ThreeExtended/loaders/KTX2Loader.js +0 -625
- package/lib/ThreeExtended/utils/BufferGeometryUtils.js +0 -846
- package/lib/ThreeExtended/utils/WorkerPool.js +0 -70
- package/lib/Utils/CameraUtils.js +0 -555
- package/lib/Utils/DEMUtils.js +0 -350
- package/lib/Utils/FeaturesUtils.js +0 -156
- package/lib/Utils/Gradients.js +0 -16
- package/lib/Utils/OrientationUtils.js +0 -457
- package/lib/Utils/ThreeUtils.js +0 -115
- package/lib/Utils/gui/C3DTilesStyle.js +0 -215
- package/lib/Utils/gui/Main.js +0 -7
- package/lib/Utils/gui/Minimap.js +0 -154
- package/lib/Utils/gui/Navigation.js +0 -245
- package/lib/Utils/gui/Scale.js +0 -107
- package/lib/Utils/gui/Searchbar.js +0 -234
- package/lib/Utils/gui/Widget.js +0 -80
- package/lib/Utils/placeObjectOnGround.js +0 -137
- package/lib/Worker/LASLoaderWorker.js +0 -19
- package/lib/Worker/Potree2Worker.js +0 -21
|
@@ -1,1025 +0,0 @@
|
|
|
1
|
-
import * as THREE from 'three';
|
|
2
|
-
import { MAIN_LOOP_EVENTS } from "../Core/MainLoop.js";
|
|
3
|
-
|
|
4
|
-
// event keycode
|
|
5
|
-
export const keys = {
|
|
6
|
-
CTRL: 17,
|
|
7
|
-
SPACE: 32,
|
|
8
|
-
T: 84,
|
|
9
|
-
Y: 89
|
|
10
|
-
};
|
|
11
|
-
const mouseButtons = {
|
|
12
|
-
LEFTCLICK: THREE.MOUSE.LEFT,
|
|
13
|
-
MIDDLECLICK: THREE.MOUSE.MIDDLE,
|
|
14
|
-
RIGHTCLICK: THREE.MOUSE.RIGHT
|
|
15
|
-
};
|
|
16
|
-
let currentPressedButton;
|
|
17
|
-
|
|
18
|
-
// starting camera position and orientation target
|
|
19
|
-
const startPosition = new THREE.Vector3();
|
|
20
|
-
const startQuaternion = new THREE.Quaternion();
|
|
21
|
-
// camera initial zoom value if orthographic
|
|
22
|
-
let cameraInitialZoom = 0;
|
|
23
|
-
|
|
24
|
-
// point under the cursor
|
|
25
|
-
const pointUnderCursor = new THREE.Vector3();
|
|
26
|
-
|
|
27
|
-
// control state
|
|
28
|
-
export const STATE = {
|
|
29
|
-
NONE: -1,
|
|
30
|
-
DRAG: 0,
|
|
31
|
-
PAN: 1,
|
|
32
|
-
ROTATE: 2,
|
|
33
|
-
TRAVEL: 3,
|
|
34
|
-
ORTHO_ZOOM: 4
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// cursor shape linked to control state
|
|
38
|
-
const cursor = {
|
|
39
|
-
default: 'auto',
|
|
40
|
-
drag: 'move',
|
|
41
|
-
pan: 'cell',
|
|
42
|
-
travel: 'wait',
|
|
43
|
-
rotate: 'move',
|
|
44
|
-
ortho_zoom: 'wait'
|
|
45
|
-
};
|
|
46
|
-
const vectorZero = new THREE.Vector3();
|
|
47
|
-
|
|
48
|
-
// mouse movement
|
|
49
|
-
const mousePosition = new THREE.Vector2();
|
|
50
|
-
const lastMousePosition = new THREE.Vector2();
|
|
51
|
-
const deltaMousePosition = new THREE.Vector2(0, 0);
|
|
52
|
-
|
|
53
|
-
// drag movement
|
|
54
|
-
const dragStart = new THREE.Vector3();
|
|
55
|
-
const dragEnd = new THREE.Vector3();
|
|
56
|
-
const dragDelta = new THREE.Vector3();
|
|
57
|
-
|
|
58
|
-
// camera focus point : ground point at screen center
|
|
59
|
-
const centerPoint = new THREE.Vector3(0, 0, 0);
|
|
60
|
-
|
|
61
|
-
// camera rotation
|
|
62
|
-
let phi = 0.0;
|
|
63
|
-
|
|
64
|
-
// displacement and rotation vectors
|
|
65
|
-
const vect = new THREE.Vector3();
|
|
66
|
-
const quat = new THREE.Quaternion();
|
|
67
|
-
const vect2 = new THREE.Vector2();
|
|
68
|
-
|
|
69
|
-
// animated travel
|
|
70
|
-
const travelEndPos = new THREE.Vector3();
|
|
71
|
-
const travelStartPos = new THREE.Vector3();
|
|
72
|
-
const travelStartRot = new THREE.Quaternion();
|
|
73
|
-
const travelEndRot = new THREE.Quaternion();
|
|
74
|
-
let travelAlpha = 0;
|
|
75
|
-
let travelDuration = 0;
|
|
76
|
-
let travelUseRotation = false;
|
|
77
|
-
let travelUseSmooth = false;
|
|
78
|
-
|
|
79
|
-
// zoom changes (for orthographic camera)
|
|
80
|
-
let startZoom = 0;
|
|
81
|
-
let endZoom = 0;
|
|
82
|
-
|
|
83
|
-
// ray caster for drag movement
|
|
84
|
-
const rayCaster = new THREE.Raycaster();
|
|
85
|
-
const plane = new THREE.Plane(new THREE.Vector3(0, 0, -1));
|
|
86
|
-
|
|
87
|
-
// default parameters :
|
|
88
|
-
const defaultOptions = {
|
|
89
|
-
enabled: true,
|
|
90
|
-
enableRotation: true,
|
|
91
|
-
rotateSpeed: 2.0,
|
|
92
|
-
minPanSpeed: 0.05,
|
|
93
|
-
maxPanSpeed: 15,
|
|
94
|
-
zoomTravelTime: 0.2,
|
|
95
|
-
// must be a number
|
|
96
|
-
zoomFactor: 2,
|
|
97
|
-
maxResolution: 1 / Infinity,
|
|
98
|
-
minResolution: Infinity,
|
|
99
|
-
maxAltitude: 50000000,
|
|
100
|
-
groundLevel: 200,
|
|
101
|
-
autoTravelTimeMin: 1.5,
|
|
102
|
-
autoTravelTimeMax: 4,
|
|
103
|
-
autoTravelTimeDist: 50000,
|
|
104
|
-
smartTravelHeightMin: 75,
|
|
105
|
-
smartTravelHeightMax: 500,
|
|
106
|
-
instantTravel: false,
|
|
107
|
-
minZenithAngle: 0,
|
|
108
|
-
maxZenithAngle: 82.5,
|
|
109
|
-
handleCollision: true,
|
|
110
|
-
minDistanceCollision: 30,
|
|
111
|
-
enableSmartTravel: true,
|
|
112
|
-
enablePan: true
|
|
113
|
-
};
|
|
114
|
-
export const PLANAR_CONTROL_EVENT = {
|
|
115
|
-
MOVED: 'moved'
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Planar controls is a camera controller adapted for a planar view, with animated movements.
|
|
120
|
-
* Usage is as follow :
|
|
121
|
-
* <ul>
|
|
122
|
-
* <li><b>Left mouse button:</b> drag the camera (translation on the (xy) world plane).</li>
|
|
123
|
-
* <li><b>Right mouse button:</b> pan the camera (translation on the vertical (z) axis of the world plane).</li>
|
|
124
|
-
* <li><b>CTRL + Left mouse button:</b> rotate the camera around the focus point.</li>
|
|
125
|
-
* <li><b>Wheel scrolling:</b> zoom toward the cursor position.</li>
|
|
126
|
-
* <li><b>Wheel clicking:</b> smart zoom toward the cursor position (animated).</li>
|
|
127
|
-
* <li><b>Y key:</b> go to the starting view (animated).</li>
|
|
128
|
-
* <li><b>T key:</b> go to the top view (animated).</li>
|
|
129
|
-
* </ul>
|
|
130
|
-
*
|
|
131
|
-
* @class PlanarControls
|
|
132
|
-
* @param {PlanarView} view the view where the controls will be used
|
|
133
|
-
* @param {object} options
|
|
134
|
-
* @param {boolean} [options.enabled=true] Set to false to disable this control
|
|
135
|
-
* @param {boolean} [options.enableRotation=true] Enable the rotation with the `CTRL + Left mouse button`
|
|
136
|
-
* and in animations, like the smart zoom.
|
|
137
|
-
* @param {boolean} [options.enableSmartTravel=true] Enable smart travel with the `wheel-click / space-bar`.
|
|
138
|
-
* @param {boolean} [options.enablePan=true] Enable pan movements with the `right-click`.
|
|
139
|
-
* @param {number} [options.rotateSpeed=2.0] Rotate speed.
|
|
140
|
-
* @param {number} [options.maxPanSpeed=15] Pan speed when close to maxAltitude.
|
|
141
|
-
* @param {number} [options.minPanSpeed=0.05] Pan speed when close to the ground.
|
|
142
|
-
* @param {number} [options.zoomTravelTime=0.2] Animation time when zooming.
|
|
143
|
-
* @param {number} [options.zoomFactor=2] The factor the scale is multiplied by when zooming
|
|
144
|
-
* in and divided by when zooming out. This factor can't be null.
|
|
145
|
-
* @param {number} [options.maxResolution=0] The smallest size in meters a pixel at the center of the
|
|
146
|
-
* view can represent.
|
|
147
|
-
* @param {number} [options.minResolution=Infinity] The biggest size in meters a pixel at the center of the
|
|
148
|
-
* view can represent.
|
|
149
|
-
* @param {number} [options.maxAltitude=12000] Maximum altitude reachable when panning or zooming out.
|
|
150
|
-
* @param {number} [options.groundLevel=200] Minimum altitude reachable when panning.
|
|
151
|
-
* @param {number} [options.autoTravelTimeMin=1.5] Minimum duration for animated travels with the `auto`
|
|
152
|
-
* parameter.
|
|
153
|
-
* @param {number} [options.autoTravelTimeMax=4] Maximum duration for animated travels with the `auto`
|
|
154
|
-
* parameter.
|
|
155
|
-
* @param {number} [options.autoTravelTimeDist=20000] Maximum travel distance for animated travel with the
|
|
156
|
-
* `auto` parameter.
|
|
157
|
-
* @param {number} [options.smartTravelHeightMin=75] Minimum height above ground reachable after a smart
|
|
158
|
-
* travel.
|
|
159
|
-
* @param {number} [options.smartTravelHeightMax=500] Maximum height above ground reachable after a smart
|
|
160
|
-
* travel.
|
|
161
|
-
* @param {boolean} [options.instantTravel=false] If set to true, animated travels will have no duration.
|
|
162
|
-
* @param {number} [options.minZenithAngle=0] The minimum reachable zenith angle for a camera
|
|
163
|
-
* rotation, in degrees.
|
|
164
|
-
* @param {number} [options.maxZenithAngle=82.5] The maximum reachable zenith angle for a camera
|
|
165
|
-
* rotation, in degrees.
|
|
166
|
-
* @param {boolean} [options.handleCollision=true]
|
|
167
|
-
*/
|
|
168
|
-
class PlanarControls extends THREE.EventDispatcher {
|
|
169
|
-
constructor(view) {
|
|
170
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
171
|
-
super();
|
|
172
|
-
this.view = view;
|
|
173
|
-
this.camera = view.camera3D;
|
|
174
|
-
|
|
175
|
-
// Set to false to disable this control
|
|
176
|
-
this.enabled = typeof options.enabled == 'boolean' ? options.enabled : defaultOptions.enabled;
|
|
177
|
-
if (this.camera.isOrthographicCamera) {
|
|
178
|
-
cameraInitialZoom = this.camera.zoom;
|
|
179
|
-
|
|
180
|
-
// enable rotation movements
|
|
181
|
-
this.enableRotation = false;
|
|
182
|
-
|
|
183
|
-
// enable pan movements
|
|
184
|
-
this.enablePan = false;
|
|
185
|
-
|
|
186
|
-
// Camera altitude is clamped under maxAltitude.
|
|
187
|
-
// This is not relevant for an orthographic camera (since the orthographic camera altitude won't change).
|
|
188
|
-
// Therefore, neutralizing by default the maxAltitude limit allows zooming out with an orthographic camera,
|
|
189
|
-
// no matter its initial position.
|
|
190
|
-
this.maxAltitude = Infinity;
|
|
191
|
-
|
|
192
|
-
// the zoom travel time (stored in `this.zoomTravelTime`) can't be `auto` with an orthographic camera
|
|
193
|
-
this.zoomTravelTime = typeof options.zoomTravelTime === 'number' ? options.zoomTravelTime : defaultOptions.zoomTravelTime;
|
|
194
|
-
} else {
|
|
195
|
-
// enable rotation movements
|
|
196
|
-
this.enableRotation = options.enableRotation === undefined ? defaultOptions.enableRotation : options.enableRotation;
|
|
197
|
-
this.rotateSpeed = options.rotateSpeed || defaultOptions.rotateSpeed;
|
|
198
|
-
|
|
199
|
-
// enable pan movements
|
|
200
|
-
this.enablePan = options.enablePan === undefined ? defaultOptions.enablePan : options.enablePan;
|
|
201
|
-
|
|
202
|
-
// minPanSpeed when close to the ground, maxPanSpeed when close to maxAltitude
|
|
203
|
-
this.minPanSpeed = options.minPanSpeed || defaultOptions.minPanSpeed;
|
|
204
|
-
this.maxPanSpeed = options.maxPanSpeed || defaultOptions.maxPanSpeed;
|
|
205
|
-
|
|
206
|
-
// camera altitude is clamped under maxAltitude
|
|
207
|
-
this.maxAltitude = options.maxAltitude || defaultOptions.maxAltitude;
|
|
208
|
-
|
|
209
|
-
// animation duration for the zoom
|
|
210
|
-
this.zoomTravelTime = options.zoomTravelTime || defaultOptions.zoomTravelTime;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// zoom movement is equal to the distance to the zoom target, multiplied by zoomFactor
|
|
214
|
-
if (options.zoomInFactor) {
|
|
215
|
-
console.warn('Controls zoomInFactor parameter is deprecated. Use zoomFactor instead.');
|
|
216
|
-
options.zoomFactor = options.zoomFactor || options.zoomInFactor;
|
|
217
|
-
}
|
|
218
|
-
if (options.zoomOutFactor) {
|
|
219
|
-
console.warn('Controls zoomOutFactor parameter is deprecated. Use zoomFactor instead.');
|
|
220
|
-
options.zoomFactor = options.zoomFactor || options.zoomInFactor || 1 / options.zoomOutFactor;
|
|
221
|
-
}
|
|
222
|
-
if (options.zoomFactor === 0) {
|
|
223
|
-
console.warn('Controls zoomFactor parameter can not be equal to 0. Its value will be set to default.');
|
|
224
|
-
options.zoomFactor = defaultOptions.zoomFactor;
|
|
225
|
-
}
|
|
226
|
-
this.zoomInFactor = options.zoomFactor || defaultOptions.zoomFactor;
|
|
227
|
-
this.zoomOutFactor = 1 / (options.zoomFactor || defaultOptions.zoomFactor);
|
|
228
|
-
|
|
229
|
-
// the maximum and minimum size (in meters) a pixel at the center of the view can represent
|
|
230
|
-
this.maxResolution = options.maxResolution || defaultOptions.maxResolution;
|
|
231
|
-
this.minResolution = options.minResolution || defaultOptions.minResolution;
|
|
232
|
-
|
|
233
|
-
// approximate ground altitude value. Camera altitude is clamped above groundLevel
|
|
234
|
-
this.groundLevel = options.groundLevel || defaultOptions.groundLevel;
|
|
235
|
-
|
|
236
|
-
// min and max duration in seconds, for animated travels with `auto` parameter
|
|
237
|
-
this.autoTravelTimeMin = options.autoTravelTimeMin || defaultOptions.autoTravelTimeMin;
|
|
238
|
-
this.autoTravelTimeMax = options.autoTravelTimeMax || defaultOptions.autoTravelTimeMax;
|
|
239
|
-
|
|
240
|
-
// max travel duration is reached for this travel distance (empirical smoothing value)
|
|
241
|
-
this.autoTravelTimeDist = options.autoTravelTimeDist || defaultOptions.autoTravelTimeDist;
|
|
242
|
-
|
|
243
|
-
// after a smartZoom, camera height above ground will be between these two values
|
|
244
|
-
if (options.smartZoomHeightMin) {
|
|
245
|
-
console.warn('Controls smartZoomHeightMin parameter is deprecated. Use smartTravelHeightMin instead.');
|
|
246
|
-
options.smartTravelHeightMin = options.smartTravelHeightMin || options.smartZoomHeightMin;
|
|
247
|
-
}
|
|
248
|
-
if (options.smartZoomHeightMax) {
|
|
249
|
-
console.warn('Controls smartZoomHeightMax parameter is deprecated. Use smartTravelHeightMax instead.');
|
|
250
|
-
options.smartTravelHeightMax = options.smartTravelHeightMax || options.smartZoomHeightMax;
|
|
251
|
-
}
|
|
252
|
-
this.smartTravelHeightMin = options.smartTravelHeightMin || defaultOptions.smartTravelHeightMin;
|
|
253
|
-
this.smartTravelHeightMax = options.smartTravelHeightMax || defaultOptions.smartTravelHeightMax;
|
|
254
|
-
|
|
255
|
-
// if set to true, animated travels have 0 duration
|
|
256
|
-
this.instantTravel = options.instantTravel || defaultOptions.instantTravel;
|
|
257
|
-
|
|
258
|
-
// the zenith angle for a camera rotation will be between these two values
|
|
259
|
-
this.minZenithAngle = (options.minZenithAngle || defaultOptions.minZenithAngle) * Math.PI / 180;
|
|
260
|
-
// max value should be less than 90 deg (90 = parallel to the ground)
|
|
261
|
-
this.maxZenithAngle = (options.maxZenithAngle || defaultOptions.maxZenithAngle) * Math.PI / 180;
|
|
262
|
-
|
|
263
|
-
// focus policy options
|
|
264
|
-
if (options.focusOnMouseOver) {
|
|
265
|
-
console.warn('Planar controls \'focusOnMouseOver\' optional parameter has been removed.');
|
|
266
|
-
}
|
|
267
|
-
if (options.focusOnMouseClick) {
|
|
268
|
-
console.warn('Planar controls \'focusOnMouseClick\' optional parameter has been removed.');
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// set collision options
|
|
272
|
-
this.handleCollision = options.handleCollision === undefined ? defaultOptions.handleCollision : options.handleCollision;
|
|
273
|
-
this.minDistanceCollision = defaultOptions.minDistanceCollision;
|
|
274
|
-
|
|
275
|
-
// enable smart travel
|
|
276
|
-
this.enableSmartTravel = options.enableSmartTravel === undefined ? defaultOptions.enableSmartTravel : options.enableSmartTravel;
|
|
277
|
-
startPosition.copy(this.camera.position);
|
|
278
|
-
startQuaternion.copy(this.camera.quaternion);
|
|
279
|
-
|
|
280
|
-
// control state
|
|
281
|
-
this.state = STATE.NONE;
|
|
282
|
-
this.cursor = cursor;
|
|
283
|
-
if (this.view.controls) {
|
|
284
|
-
// esLint-disable-next-line no-console
|
|
285
|
-
console.warn('Deprecated use of PlanarControls. See examples to correct PlanarControls implementation.');
|
|
286
|
-
this.view.controls.dispose();
|
|
287
|
-
}
|
|
288
|
-
this.view.controls = this;
|
|
289
|
-
|
|
290
|
-
// eventListeners handlers
|
|
291
|
-
this._handlerOnKeyDown = this.onKeyDown.bind(this);
|
|
292
|
-
this._handlerOnMouseDown = this.onMouseDown.bind(this);
|
|
293
|
-
this._handlerOnMouseUp = this.onMouseUp.bind(this);
|
|
294
|
-
this._handlerOnMouseMove = this.onMouseMove.bind(this);
|
|
295
|
-
this._handlerOnMouseWheel = this.onMouseWheel.bind(this);
|
|
296
|
-
this._handlerContextMenu = this.onContextMenu.bind(this);
|
|
297
|
-
this._handlerUpdate = this.update.bind(this);
|
|
298
|
-
|
|
299
|
-
// add this PlanarControl instance to the view's frameRequesters
|
|
300
|
-
// with this, PlanarControl.update() will be called each frame
|
|
301
|
-
this.view.addFrameRequester(MAIN_LOOP_EVENTS.AFTER_CAMERA_UPDATE, this._handlerUpdate);
|
|
302
|
-
|
|
303
|
-
// event listeners for user input (to activate the controls)
|
|
304
|
-
this.addInputListeners();
|
|
305
|
-
}
|
|
306
|
-
dispose() {
|
|
307
|
-
this.removeInputListeners();
|
|
308
|
-
this.view.removeFrameRequester(MAIN_LOOP_EVENTS.AFTER_CAMERA_UPDATE, this._handlerUpdate);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* update the view and camera if needed, and handles the animated travel
|
|
313
|
-
* @param {number} dt the delta time between two updates in millisecond
|
|
314
|
-
* @param {boolean} updateLoopRestarted true if we just started rendering
|
|
315
|
-
* @ignore
|
|
316
|
-
*/
|
|
317
|
-
update(dt, updateLoopRestarted) {
|
|
318
|
-
// dt will not be relevant when we just started rendering. We consider a 1-frame move in this case
|
|
319
|
-
if (updateLoopRestarted) {
|
|
320
|
-
dt = 16;
|
|
321
|
-
}
|
|
322
|
-
const onMovement = this.state !== STATE.NONE;
|
|
323
|
-
switch (this.state) {
|
|
324
|
-
case STATE.TRAVEL:
|
|
325
|
-
this.handleTravel(dt);
|
|
326
|
-
this.view.notifyChange(this.camera);
|
|
327
|
-
break;
|
|
328
|
-
case STATE.ORTHO_ZOOM:
|
|
329
|
-
this.handleZoomOrtho(dt);
|
|
330
|
-
this.view.notifyChange(this.camera);
|
|
331
|
-
break;
|
|
332
|
-
case STATE.DRAG:
|
|
333
|
-
this.handleDragMovement();
|
|
334
|
-
this.view.notifyChange(this.camera);
|
|
335
|
-
break;
|
|
336
|
-
case STATE.ROTATE:
|
|
337
|
-
this.handleRotation();
|
|
338
|
-
this.view.notifyChange(this.camera);
|
|
339
|
-
break;
|
|
340
|
-
case STATE.PAN:
|
|
341
|
-
this.handlePanMovement();
|
|
342
|
-
this.view.notifyChange(this.camera);
|
|
343
|
-
break;
|
|
344
|
-
case STATE.NONE:
|
|
345
|
-
default:
|
|
346
|
-
break;
|
|
347
|
-
}
|
|
348
|
-
// We test if camera collides to the geometry layer or is too close to the ground, and adjust its altitude in
|
|
349
|
-
// case
|
|
350
|
-
if (this.handleCollision) {
|
|
351
|
-
// check distance to the ground/surface geometry (could be another geometry layer)
|
|
352
|
-
this.view.camera.adjustAltitudeToAvoidCollisionWithLayer(this.view, this.view.tileLayer, this.minDistanceCollision);
|
|
353
|
-
}
|
|
354
|
-
if (onMovement) {
|
|
355
|
-
this.view.dispatchEvent({
|
|
356
|
-
type: PLANAR_CONTROL_EVENT.MOVED
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
deltaMousePosition.set(0, 0);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Initiate a drag movement (translation on (xy) plane). The movement value is derived from the actual world
|
|
364
|
-
* point under the mouse cursor. This allows user to 'grab' a world point and drag it to move.
|
|
365
|
-
*
|
|
366
|
-
* @ignore
|
|
367
|
-
*/
|
|
368
|
-
initiateDrag() {
|
|
369
|
-
this.state = STATE.DRAG;
|
|
370
|
-
|
|
371
|
-
// the world point under mouse cursor when the drag movement is started
|
|
372
|
-
dragStart.copy(this.getWorldPointAtScreenXY(mousePosition));
|
|
373
|
-
|
|
374
|
-
// the difference between start and end cursor position
|
|
375
|
-
dragDelta.set(0, 0, 0);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Handle the drag movement (translation on (xy) plane) when user moves the mouse while in STATE.DRAG. The
|
|
380
|
-
* drag movement is previously initiated by [initiateDrag]{@link PlanarControls#initiateDrag}. Compute the
|
|
381
|
-
* drag value and update the camera controls. The movement value is derived from the actual world point under
|
|
382
|
-
* the mouse cursor. This allows the user to 'grab' a world point and drag it to move.
|
|
383
|
-
*
|
|
384
|
-
* @ignore
|
|
385
|
-
*/
|
|
386
|
-
handleDragMovement() {
|
|
387
|
-
// the world point under the current mouse cursor position, at same altitude than dragStart
|
|
388
|
-
this.getWorldPointFromMathPlaneAtScreenXY(mousePosition, dragStart.z, dragEnd);
|
|
389
|
-
|
|
390
|
-
// the difference between start and end cursor position
|
|
391
|
-
dragDelta.subVectors(dragStart, dragEnd);
|
|
392
|
-
|
|
393
|
-
// update the camera position
|
|
394
|
-
this.camera.position.add(dragDelta);
|
|
395
|
-
dragDelta.set(0, 0, 0);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Initiate a pan movement (local translation on (xz) plane).
|
|
400
|
-
*
|
|
401
|
-
* @ignore
|
|
402
|
-
*/
|
|
403
|
-
initiatePan() {
|
|
404
|
-
this.state = STATE.PAN;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Handle the pan movement (translation on local x / world z plane) when user moves the mouse while
|
|
409
|
-
* STATE.PAN. The drag movement is previously initiated by [initiatePan]{@link PlanarControls#initiatePan}.
|
|
410
|
-
* Compute the pan value and update the camera controls.
|
|
411
|
-
*
|
|
412
|
-
* @ignore
|
|
413
|
-
*/
|
|
414
|
-
handlePanMovement() {
|
|
415
|
-
vect.set(-deltaMousePosition.x, deltaMousePosition.y, 0);
|
|
416
|
-
this.camera.localToWorld(vect);
|
|
417
|
-
this.camera.position.copy(vect);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* Initiate a rotate (orbit) movement.
|
|
422
|
-
*
|
|
423
|
-
* @ignore
|
|
424
|
-
*/
|
|
425
|
-
initiateRotation() {
|
|
426
|
-
this.state = STATE.ROTATE;
|
|
427
|
-
centerPoint.copy(this.getWorldPointAtScreenXY(new THREE.Vector2(0.5 * this.view.mainLoop.gfxEngine.width, 0.5 * this.view.mainLoop.gfxEngine.height)));
|
|
428
|
-
const radius = this.camera.position.distanceTo(centerPoint);
|
|
429
|
-
phi = Math.acos((this.camera.position.z - centerPoint.z) / radius);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/**
|
|
433
|
-
* Handle the rotate movement (orbit) when user moves the mouse while in STATE.ROTATE. The movement is an
|
|
434
|
-
* orbit around `centerPoint`, the camera focus point (ground point at screen center). The rotate movement
|
|
435
|
-
* is previously initiated in [initiateRotation]{@link PlanarControls#initiateRotation}.
|
|
436
|
-
* Compute the new position value and update the camera controls.
|
|
437
|
-
*
|
|
438
|
-
* @ignore
|
|
439
|
-
*/
|
|
440
|
-
handleRotation() {
|
|
441
|
-
// angle deltas
|
|
442
|
-
// deltaMousePosition is computed in onMouseMove / onMouseDowns
|
|
443
|
-
const thetaDelta = -this.rotateSpeed * deltaMousePosition.x / this.view.mainLoop.gfxEngine.width;
|
|
444
|
-
const phiDelta = -this.rotateSpeed * deltaMousePosition.y / this.view.mainLoop.gfxEngine.height;
|
|
445
|
-
|
|
446
|
-
// the vector from centerPoint (focus point) to camera position
|
|
447
|
-
const offset = this.camera.position.clone().sub(centerPoint);
|
|
448
|
-
if (thetaDelta !== 0 || phiDelta !== 0) {
|
|
449
|
-
if (phi + phiDelta >= this.minZenithAngle && phi + phiDelta <= this.maxZenithAngle && phiDelta !== 0) {
|
|
450
|
-
// rotation around X (altitude)
|
|
451
|
-
phi += phiDelta;
|
|
452
|
-
vect.set(0, 0, 1);
|
|
453
|
-
quat.setFromUnitVectors(this.camera.up, vect);
|
|
454
|
-
offset.applyQuaternion(quat);
|
|
455
|
-
vect.setFromMatrixColumn(this.camera.matrix, 0);
|
|
456
|
-
quat.setFromAxisAngle(vect, phiDelta);
|
|
457
|
-
offset.applyQuaternion(quat);
|
|
458
|
-
vect.set(0, 0, 1);
|
|
459
|
-
quat.setFromUnitVectors(this.camera.up, vect).invert();
|
|
460
|
-
offset.applyQuaternion(quat);
|
|
461
|
-
}
|
|
462
|
-
if (thetaDelta !== 0) {
|
|
463
|
-
// rotation around Z (azimuth)
|
|
464
|
-
vect.set(0, 0, 1);
|
|
465
|
-
quat.setFromAxisAngle(vect, thetaDelta);
|
|
466
|
-
offset.applyQuaternion(quat);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
this.camera.position.copy(offset);
|
|
470
|
-
// TODO : lookAt calls an updateMatrixWorld(). It should be replaced by a new method that does not.
|
|
471
|
-
this.camera.lookAt(vectorZero);
|
|
472
|
-
this.camera.position.add(centerPoint);
|
|
473
|
-
this.camera.updateMatrixWorld();
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* Triggers a Zoom animated movement (travel) toward / away from the world point under the mouse cursor. The
|
|
478
|
-
* zoom intensity varies according to the distance between the camera and the point. The closer to the ground,
|
|
479
|
-
* the lower the intensity. Orientation will not change (null parameter in the call to
|
|
480
|
-
* [initiateTravel]{@link PlanarControls#initiateTravel} function).
|
|
481
|
-
*
|
|
482
|
-
* @param {Event} event the mouse wheel event.
|
|
483
|
-
* @ignore
|
|
484
|
-
*/
|
|
485
|
-
initiateZoom(event) {
|
|
486
|
-
const delta = -event.deltaY;
|
|
487
|
-
pointUnderCursor.copy(this.getWorldPointAtScreenXY(mousePosition));
|
|
488
|
-
const newPos = new THREE.Vector3();
|
|
489
|
-
if (delta > 0 || delta < 0 && this.maxAltitude > this.camera.position.z) {
|
|
490
|
-
const zoomFactor = delta > 0 ? this.zoomInFactor : this.zoomOutFactor;
|
|
491
|
-
|
|
492
|
-
// do not zoom if the resolution after the zoom is outside resolution limits
|
|
493
|
-
const endResolution = this.view.getPixelsToMeters() / zoomFactor;
|
|
494
|
-
if (this.maxResolution > endResolution || endResolution > this.minResolution) {
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
// change the camera field of view if the camera is orthographic
|
|
499
|
-
if (this.camera.isOrthographicCamera) {
|
|
500
|
-
// switch state to STATE.ZOOM
|
|
501
|
-
this.state = STATE.ORTHO_ZOOM;
|
|
502
|
-
this.view.notifyChange(this.camera);
|
|
503
|
-
|
|
504
|
-
// camera zoom at the beginning of zoom movement
|
|
505
|
-
startZoom = this.camera.zoom;
|
|
506
|
-
// camera zoom at the end of zoom movement
|
|
507
|
-
endZoom = startZoom * zoomFactor;
|
|
508
|
-
// the altitude of the target must be the same as camera's
|
|
509
|
-
pointUnderCursor.z = this.camera.position.z;
|
|
510
|
-
travelAlpha = 0;
|
|
511
|
-
travelDuration = this.zoomTravelTime;
|
|
512
|
-
this.updateMouseCursorType();
|
|
513
|
-
} else {
|
|
514
|
-
// target position
|
|
515
|
-
newPos.lerpVectors(this.camera.position, pointUnderCursor, 1 - 1 / zoomFactor);
|
|
516
|
-
// initiate travel
|
|
517
|
-
this.initiateTravel(newPos, this.zoomTravelTime, null, false);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
/**
|
|
523
|
-
* Handle the animated zoom change for an orthographic camera, when state is `ZOOM`.
|
|
524
|
-
*
|
|
525
|
-
* @param {number} dt the delta time between two updates in milliseconds
|
|
526
|
-
* @ignore
|
|
527
|
-
*/
|
|
528
|
-
handleZoomOrtho(dt) {
|
|
529
|
-
travelAlpha = Math.min(travelAlpha + dt / 1000 / travelDuration, 1);
|
|
530
|
-
|
|
531
|
-
// new zoom
|
|
532
|
-
const zoom = startZoom + travelAlpha * (endZoom - startZoom);
|
|
533
|
-
if (this.camera.zoom !== zoom) {
|
|
534
|
-
// zoom has changed
|
|
535
|
-
this.camera.zoom = zoom;
|
|
536
|
-
this.camera.updateProjectionMatrix();
|
|
537
|
-
|
|
538
|
-
// current world coordinates under the mouse
|
|
539
|
-
this.view.viewToNormalizedCoords(mousePosition, vect);
|
|
540
|
-
vect.z = 0;
|
|
541
|
-
vect.unproject(this.camera);
|
|
542
|
-
|
|
543
|
-
// new camera position
|
|
544
|
-
this.camera.position.x += pointUnderCursor.x - vect.x;
|
|
545
|
-
this.camera.position.y += pointUnderCursor.y - vect.y;
|
|
546
|
-
this.camera.updateMatrixWorld(true);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// completion test
|
|
550
|
-
this.testAnimationEnd();
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* Triggers a 'smart zoom' animated movement (travel) toward the point under mouse cursor. The camera will be
|
|
555
|
-
* smoothly moved and oriented close to the target, at a determined height and distance.
|
|
556
|
-
*
|
|
557
|
-
* @ignore
|
|
558
|
-
*/
|
|
559
|
-
initiateSmartTravel() {
|
|
560
|
-
const pointUnderCursor = this.getWorldPointAtScreenXY(mousePosition);
|
|
561
|
-
|
|
562
|
-
// direction of the movement, projected on xy plane and normalized
|
|
563
|
-
const dir = new THREE.Vector3();
|
|
564
|
-
dir.copy(pointUnderCursor).sub(this.camera.position);
|
|
565
|
-
dir.z = 0;
|
|
566
|
-
dir.normalize();
|
|
567
|
-
const distanceToPoint = this.camera.position.distanceTo(pointUnderCursor);
|
|
568
|
-
|
|
569
|
-
// camera height (altitude above ground) at the end of the travel, 5000 is an empirical smoothing distance
|
|
570
|
-
const targetHeight = THREE.MathUtils.lerp(this.smartTravelHeightMin, this.smartTravelHeightMax, Math.min(distanceToPoint / 5000, 1));
|
|
571
|
-
|
|
572
|
-
// camera position at the end of the travel
|
|
573
|
-
const moveTarget = new THREE.Vector3();
|
|
574
|
-
moveTarget.copy(pointUnderCursor);
|
|
575
|
-
if (this.enableRotation) {
|
|
576
|
-
moveTarget.add(dir.multiplyScalar(-targetHeight * 2));
|
|
577
|
-
}
|
|
578
|
-
moveTarget.z = pointUnderCursor.z + targetHeight;
|
|
579
|
-
if (this.camera.isOrthographicCamera) {
|
|
580
|
-
startZoom = this.camera.zoom;
|
|
581
|
-
// camera zoom at the end of the travel, 5000 is an empirical smoothing distance
|
|
582
|
-
endZoom = startZoom * (1 + Math.min(distanceToPoint / 5000, 1));
|
|
583
|
-
moveTarget.z = this.camera.position.z;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// initiate the travel
|
|
587
|
-
this.initiateTravel(moveTarget, 'auto', pointUnderCursor, true);
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* Triggers an animated movement and rotation for the camera.
|
|
592
|
-
*
|
|
593
|
-
* @param {THREE.Vector3} targetPos The target position of the camera (reached at the end).
|
|
594
|
-
* @param {number|string} travelTime Set to `auto` or set to a duration in seconds. If set to `auto`,
|
|
595
|
-
* travel time will be set to a duration between `autoTravelTimeMin` and `autoTravelTimeMax` according to
|
|
596
|
-
* the distance and the angular difference between start and finish.
|
|
597
|
-
* @param {(string|THREE.Vector3|THREE.Quaternion)} targetOrientation define the target rotation of
|
|
598
|
-
* the camera :
|
|
599
|
-
* <ul>
|
|
600
|
-
* <li>if targetOrientation is a world point (Vector3) : the camera will lookAt() this point</li>
|
|
601
|
-
* <li>if targetOrientation is a quaternion : this quaternion will define the final camera orientation </li>
|
|
602
|
-
* <li>if targetOrientation is neither a world point nor a quaternion : the camera will keep its starting
|
|
603
|
-
* orientation</li>
|
|
604
|
-
* </ul>
|
|
605
|
-
* @param {boolean} useSmooth animation is smoothed using the `smooth(value)` function (slower
|
|
606
|
-
* at start and finish).
|
|
607
|
-
*
|
|
608
|
-
* @ignore
|
|
609
|
-
*/
|
|
610
|
-
initiateTravel(targetPos, travelTime, targetOrientation, useSmooth) {
|
|
611
|
-
this.state = STATE.TRAVEL;
|
|
612
|
-
this.view.notifyChange(this.camera);
|
|
613
|
-
// the progress of the travel (animation alpha)
|
|
614
|
-
travelAlpha = 0;
|
|
615
|
-
// update cursor
|
|
616
|
-
this.updateMouseCursorType();
|
|
617
|
-
travelUseRotation = this.enableRotation && targetOrientation && (targetOrientation.isQuaternion || targetOrientation.isVector3);
|
|
618
|
-
travelUseSmooth = useSmooth;
|
|
619
|
-
|
|
620
|
-
// start position (current camera position)
|
|
621
|
-
travelStartPos.copy(this.camera.position);
|
|
622
|
-
|
|
623
|
-
// start rotation (current camera rotation)
|
|
624
|
-
travelStartRot.copy(this.camera.quaternion);
|
|
625
|
-
|
|
626
|
-
// setup the end rotation :
|
|
627
|
-
if (travelUseRotation) {
|
|
628
|
-
if (targetOrientation.isQuaternion) {
|
|
629
|
-
// case where targetOrientation is a quaternion
|
|
630
|
-
travelEndRot.copy(targetOrientation);
|
|
631
|
-
} else if (targetOrientation.isVector3) {
|
|
632
|
-
// case where targetOrientation is a Vector3
|
|
633
|
-
if (targetPos === targetOrientation) {
|
|
634
|
-
this.camera.lookAt(targetOrientation);
|
|
635
|
-
travelEndRot.copy(this.camera.quaternion);
|
|
636
|
-
this.camera.quaternion.copy(travelStartRot);
|
|
637
|
-
} else {
|
|
638
|
-
this.camera.position.copy(targetPos);
|
|
639
|
-
this.camera.lookAt(targetOrientation);
|
|
640
|
-
travelEndRot.copy(this.camera.quaternion);
|
|
641
|
-
this.camera.quaternion.copy(travelStartRot);
|
|
642
|
-
this.camera.position.copy(travelStartPos);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// end position
|
|
648
|
-
travelEndPos.copy(targetPos);
|
|
649
|
-
|
|
650
|
-
// beginning of the travel duration setup
|
|
651
|
-
if (this.instantTravel) {
|
|
652
|
-
travelDuration = 0;
|
|
653
|
-
} else if (travelTime === 'auto') {
|
|
654
|
-
// case where travelTime is set to `auto` : travelDuration will be a value between autoTravelTimeMin and
|
|
655
|
-
// autoTravelTimeMax depending on travel distance and travel angular difference
|
|
656
|
-
|
|
657
|
-
// a value between 0 and 1 according to the travel distance. Adjusted by autoTravelTimeDist parameter
|
|
658
|
-
const normalizedDistance = Math.min(1, targetPos.distanceTo(this.camera.position) / this.autoTravelTimeDist);
|
|
659
|
-
travelDuration = THREE.MathUtils.lerp(this.autoTravelTimeMin, this.autoTravelTimeMax, normalizedDistance);
|
|
660
|
-
|
|
661
|
-
// if travel changes camera orientation, travel duration is adjusted according to angularDifference
|
|
662
|
-
// this allows for a smoother travel (more time for the camera to rotate)
|
|
663
|
-
// final duration will not exceed autoTravelTimeMax
|
|
664
|
-
if (travelUseRotation) {
|
|
665
|
-
// value is normalized between 0 and 1
|
|
666
|
-
const angularDifference = 0.5 - 0.5 * travelEndRot.normalize().dot(this.camera.quaternion.normalize());
|
|
667
|
-
travelDuration *= 1 + 2 * angularDifference;
|
|
668
|
-
travelDuration = Math.min(travelDuration, this.autoTravelTimeMax);
|
|
669
|
-
}
|
|
670
|
-
} else {
|
|
671
|
-
// case where travelTime !== `auto` : travelTime is a duration in seconds given as parameter
|
|
672
|
-
travelDuration = travelTime;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
/**
|
|
677
|
-
* Handle the animated movement and rotation of the camera in `travel` state.
|
|
678
|
-
*
|
|
679
|
-
* @param {number} dt the delta time between two updates in milliseconds
|
|
680
|
-
* @ignore
|
|
681
|
-
*/
|
|
682
|
-
handleTravel(dt) {
|
|
683
|
-
travelAlpha = Math.min(travelAlpha + dt / 1000 / travelDuration, 1);
|
|
684
|
-
|
|
685
|
-
// the animation alpha, between 0 (start) and 1 (finish)
|
|
686
|
-
const alpha = travelUseSmooth ? this.smooth(travelAlpha) : travelAlpha;
|
|
687
|
-
|
|
688
|
-
// new position
|
|
689
|
-
this.camera.position.lerpVectors(travelStartPos, travelEndPos, alpha);
|
|
690
|
-
const zoom = startZoom + alpha * (endZoom - startZoom);
|
|
691
|
-
// new zoom
|
|
692
|
-
if (this.camera.isOrthographicCamera && this.camera.zoom !== zoom) {
|
|
693
|
-
this.camera.zoom = zoom;
|
|
694
|
-
this.camera.updateProjectionMatrix();
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
// new rotation
|
|
698
|
-
if (travelUseRotation === true) {
|
|
699
|
-
this.camera.quaternion.slerpQuaternions(travelStartRot, travelEndRot, alpha);
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
// completion test
|
|
703
|
-
this.testAnimationEnd();
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
/**
|
|
707
|
-
* Test if the currently running animation is finished (travelAlpha reached 1).
|
|
708
|
-
* If it is, reset controls to state NONE.
|
|
709
|
-
*
|
|
710
|
-
* @ignore
|
|
711
|
-
*/
|
|
712
|
-
testAnimationEnd() {
|
|
713
|
-
if (travelAlpha === 1) {
|
|
714
|
-
// Resume normal behaviour after animation is completed
|
|
715
|
-
this.state = STATE.NONE;
|
|
716
|
-
this.updateMouseCursorType();
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
/**
|
|
721
|
-
* Triggers an animated movement (travel) to set the camera to top view, above the focus point,
|
|
722
|
-
* at altitude = distanceToFocusPoint.
|
|
723
|
-
*
|
|
724
|
-
* @ignore
|
|
725
|
-
*/
|
|
726
|
-
goToTopView() {
|
|
727
|
-
const topViewPos = new THREE.Vector3();
|
|
728
|
-
const targetQuat = new THREE.Quaternion();
|
|
729
|
-
|
|
730
|
-
// the top view position is above the camera focus point, at an altitude = distanceToPoint
|
|
731
|
-
topViewPos.copy(this.getWorldPointAtScreenXY(new THREE.Vector2(0.5 * this.view.mainLoop.gfxEngine.width, 0.5 * this.view.mainLoop.gfxEngine.height)));
|
|
732
|
-
topViewPos.z += Math.min(this.maxAltitude, this.camera.position.distanceTo(topViewPos));
|
|
733
|
-
targetQuat.setFromAxisAngle(new THREE.Vector3(1, 0, 0), 0);
|
|
734
|
-
|
|
735
|
-
// initiate the travel
|
|
736
|
-
this.initiateTravel(topViewPos, 'auto', targetQuat, true);
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
/**
|
|
740
|
-
* Triggers an animated movement (travel) to set the camera to starting view
|
|
741
|
-
*
|
|
742
|
-
* @ignore
|
|
743
|
-
*/
|
|
744
|
-
goToStartView() {
|
|
745
|
-
// if startZoom and endZoom have not been set yet, give them neutral values
|
|
746
|
-
if (this.camera.isOrthographicCamera) {
|
|
747
|
-
startZoom = this.camera.zoom;
|
|
748
|
-
endZoom = cameraInitialZoom;
|
|
749
|
-
}
|
|
750
|
-
this.initiateTravel(startPosition, 'auto', startQuaternion, true);
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
/**
|
|
754
|
-
* Returns the world point (xyz) under the posXY screen point. The point belong to an abstract mathematical
|
|
755
|
-
* plane of specified altitude (does not us actual geometry).
|
|
756
|
-
*
|
|
757
|
-
* @param {THREE.Vector2} posXY the mouse position in screen space (unit : pixel)
|
|
758
|
-
* @param {number} altitude the altitude (z) of the mathematical plane
|
|
759
|
-
* @param {THREE.Vector3} target the target vector3
|
|
760
|
-
* @return {THREE.Vector3}
|
|
761
|
-
* @ignore
|
|
762
|
-
*/
|
|
763
|
-
getWorldPointFromMathPlaneAtScreenXY(posXY, altitude) {
|
|
764
|
-
let target = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new THREE.Vector3();
|
|
765
|
-
vect2.copy(this.view.viewToNormalizedCoords(posXY));
|
|
766
|
-
rayCaster.setFromCamera(vect2, this.camera);
|
|
767
|
-
plane.constant = altitude;
|
|
768
|
-
rayCaster.ray.intersectPlane(plane, target);
|
|
769
|
-
return target;
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
/**
|
|
773
|
-
* Returns the world point (xyz) under the posXY screen point. If geometry is under the cursor, the point is
|
|
774
|
-
* obtained with getPickingPositionFromDepth. If no geometry is under the cursor, the point is obtained with
|
|
775
|
-
* [getWorldPointFromMathPlaneAtScreenXY]{@link PlanarControls#getWorldPointFromMathPlaneAtScreenXY}.
|
|
776
|
-
*
|
|
777
|
-
* @param {THREE.Vector2} posXY the mouse position in screen space (unit : pixel)
|
|
778
|
-
* @param {THREE.Vector3} target the target World coordinates.
|
|
779
|
-
* @return {THREE.Vector3}
|
|
780
|
-
* @ignore
|
|
781
|
-
*/
|
|
782
|
-
getWorldPointAtScreenXY(posXY) {
|
|
783
|
-
let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new THREE.Vector3();
|
|
784
|
-
// check if there is a valid geometry under cursor
|
|
785
|
-
if (this.view.getPickingPositionFromDepth(posXY, target)) {
|
|
786
|
-
return target;
|
|
787
|
-
} else {
|
|
788
|
-
// if not, we use the mathematical plane at altitude = groundLevel
|
|
789
|
-
this.getWorldPointFromMathPlaneAtScreenXY(posXY, this.groundLevel, target);
|
|
790
|
-
return target;
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
/**
|
|
795
|
-
* Add all the input event listeners (activate the controls).
|
|
796
|
-
*
|
|
797
|
-
* @ignore
|
|
798
|
-
*/
|
|
799
|
-
addInputListeners() {
|
|
800
|
-
this.view.domElement.addEventListener('keydown', this._handlerOnKeyDown, false);
|
|
801
|
-
this.view.domElement.addEventListener('mousedown', this._handlerOnMouseDown, false);
|
|
802
|
-
this.view.domElement.addEventListener('mouseup', this._handlerOnMouseUp, false);
|
|
803
|
-
this.view.domElement.addEventListener('mouseleave', this._handlerOnMouseUp, false);
|
|
804
|
-
this.view.domElement.addEventListener('mousemove', this._handlerOnMouseMove, false);
|
|
805
|
-
this.view.domElement.addEventListener('wheel', this._handlerOnMouseWheel, false);
|
|
806
|
-
// prevent the default context menu from appearing when right-clicking
|
|
807
|
-
// this allows to use right-click for input without the menu appearing
|
|
808
|
-
this.view.domElement.addEventListener('contextmenu', this._handlerContextMenu, false);
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
/**
|
|
812
|
-
* Removes all the input listeners (deactivate the controls).
|
|
813
|
-
*
|
|
814
|
-
* @ignore
|
|
815
|
-
*/
|
|
816
|
-
removeInputListeners() {
|
|
817
|
-
this.view.domElement.removeEventListener('keydown', this._handlerOnKeyDown, true);
|
|
818
|
-
this.view.domElement.removeEventListener('mousedown', this._handlerOnMouseDown, false);
|
|
819
|
-
this.view.domElement.removeEventListener('mouseup', this._handlerOnMouseUp, false);
|
|
820
|
-
this.view.domElement.removeEventListener('mouseleave', this._handlerOnMouseUp, false);
|
|
821
|
-
this.view.domElement.removeEventListener('mousemove', this._handlerOnMouseMove, false);
|
|
822
|
-
this.view.domElement.removeEventListener('wheel', this._handlerOnMouseWheel, false);
|
|
823
|
-
this.view.domElement.removeEventListener('contextmenu', this._handlerContextMenu, false);
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
/**
|
|
827
|
-
* Update the cursor image according to the control state.
|
|
828
|
-
*
|
|
829
|
-
* @ignore
|
|
830
|
-
*/
|
|
831
|
-
updateMouseCursorType() {
|
|
832
|
-
switch (this.state) {
|
|
833
|
-
case STATE.NONE:
|
|
834
|
-
this.view.domElement.style.cursor = this.cursor.default;
|
|
835
|
-
break;
|
|
836
|
-
case STATE.DRAG:
|
|
837
|
-
this.view.domElement.style.cursor = this.cursor.drag;
|
|
838
|
-
break;
|
|
839
|
-
case STATE.PAN:
|
|
840
|
-
this.view.domElement.style.cursor = this.cursor.pan;
|
|
841
|
-
break;
|
|
842
|
-
case STATE.TRAVEL:
|
|
843
|
-
this.view.domElement.style.cursor = this.cursor.travel;
|
|
844
|
-
break;
|
|
845
|
-
case STATE.ORTHO_ZOOM:
|
|
846
|
-
this.view.domElement.style.cursor = this.cursor.ortho_zoom;
|
|
847
|
-
break;
|
|
848
|
-
case STATE.ROTATE:
|
|
849
|
-
this.view.domElement.style.cursor = this.cursor.rotate;
|
|
850
|
-
break;
|
|
851
|
-
default:
|
|
852
|
-
break;
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
updateMousePositionAndDelta(event) {
|
|
856
|
-
this.view.eventToViewCoords(event, mousePosition);
|
|
857
|
-
deltaMousePosition.copy(mousePosition).sub(lastMousePosition);
|
|
858
|
-
lastMousePosition.copy(mousePosition);
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
/**
|
|
862
|
-
* cursor modification for a specifique state.
|
|
863
|
-
*
|
|
864
|
-
* @param {string} state the state in which we want to change the cursor ('default', 'drag', 'pan', 'travel', 'rotate').
|
|
865
|
-
* @param {string} newCursor the css cursor we want to have for the specified state.
|
|
866
|
-
* @ignore
|
|
867
|
-
*/
|
|
868
|
-
setCursor(state, newCursor) {
|
|
869
|
-
this.cursor[state] = newCursor;
|
|
870
|
-
this.updateMouseCursorType();
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
/**
|
|
874
|
-
* Catch and manage the event when a touch on the mouse is downs.
|
|
875
|
-
*
|
|
876
|
-
* @param {Event} event the current event (mouse left or right button clicked, mouse wheel button actioned).
|
|
877
|
-
* @ignore
|
|
878
|
-
*/
|
|
879
|
-
onMouseDown(event) {
|
|
880
|
-
if (!this.enabled) {
|
|
881
|
-
return;
|
|
882
|
-
}
|
|
883
|
-
event.preventDefault();
|
|
884
|
-
this.view.domElement.focus();
|
|
885
|
-
if (STATE.NONE !== this.state) {
|
|
886
|
-
return;
|
|
887
|
-
}
|
|
888
|
-
currentPressedButton = event.button;
|
|
889
|
-
this.updateMousePositionAndDelta(event);
|
|
890
|
-
if (mouseButtons.LEFTCLICK === event.button) {
|
|
891
|
-
if (event.ctrlKey) {
|
|
892
|
-
if (this.enableRotation) {
|
|
893
|
-
this.initiateRotation();
|
|
894
|
-
} else {
|
|
895
|
-
return;
|
|
896
|
-
}
|
|
897
|
-
} else {
|
|
898
|
-
this.initiateDrag();
|
|
899
|
-
}
|
|
900
|
-
} else if (mouseButtons.MIDDLECLICK === event.button) {
|
|
901
|
-
if (this.enableSmartTravel) {
|
|
902
|
-
this.initiateSmartTravel();
|
|
903
|
-
} else {
|
|
904
|
-
return;
|
|
905
|
-
}
|
|
906
|
-
} else if (mouseButtons.RIGHTCLICK === event.button) {
|
|
907
|
-
if (this.enablePan) {
|
|
908
|
-
this.initiatePan();
|
|
909
|
-
} else {
|
|
910
|
-
return;
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
this.updateMouseCursorType();
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
/**
|
|
917
|
-
* Catch and manage the event when a touch on the mouse is released.
|
|
918
|
-
*
|
|
919
|
-
* @param {Event} event the current event
|
|
920
|
-
* @ignore
|
|
921
|
-
*/
|
|
922
|
-
onMouseUp(event) {
|
|
923
|
-
event.preventDefault();
|
|
924
|
-
|
|
925
|
-
// Does not interrupt ongoing camera action if state is TRAVEL or CAMERA_OTHO. This prevents interrupting a zoom
|
|
926
|
-
// movement or a smart travel by pressing any movement key.
|
|
927
|
-
// The camera action is also uninterrupted if the released button does not match the button triggering the
|
|
928
|
-
// ongoing action. This prevents for instance exiting drag mode when right-clicking while dragging the view.
|
|
929
|
-
if (STATE.TRAVEL !== this.state && STATE.ORTHO_ZOOM !== this.state && currentPressedButton === event.button) {
|
|
930
|
-
this.state = STATE.NONE;
|
|
931
|
-
}
|
|
932
|
-
this.updateMouseCursorType();
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
/**
|
|
936
|
-
* Catch and manage the event when the mouse is moved.
|
|
937
|
-
*
|
|
938
|
-
* @param {Event} event the current event.
|
|
939
|
-
* @ignore
|
|
940
|
-
*/
|
|
941
|
-
onMouseMove(event) {
|
|
942
|
-
if (!this.enabled) {
|
|
943
|
-
return;
|
|
944
|
-
}
|
|
945
|
-
event.preventDefault();
|
|
946
|
-
this.updateMousePositionAndDelta(event);
|
|
947
|
-
|
|
948
|
-
// notify change if moving
|
|
949
|
-
if (STATE.NONE !== this.state) {
|
|
950
|
-
this.view.notifyChange();
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
/**
|
|
955
|
-
* Catch and manage the event when a key is down.
|
|
956
|
-
*
|
|
957
|
-
* @param {Event} event the current event
|
|
958
|
-
* @ignore
|
|
959
|
-
*/
|
|
960
|
-
onKeyDown(event) {
|
|
961
|
-
if (STATE.NONE !== this.state || !this.enabled) {
|
|
962
|
-
return;
|
|
963
|
-
}
|
|
964
|
-
switch (event.keyCode) {
|
|
965
|
-
case keys.T:
|
|
966
|
-
// going to top view is not relevant for an orthographic camera, since it is always top view
|
|
967
|
-
if (!this.camera.isOrthographicCamera) {
|
|
968
|
-
this.goToTopView();
|
|
969
|
-
}
|
|
970
|
-
break;
|
|
971
|
-
case keys.Y:
|
|
972
|
-
this.goToStartView();
|
|
973
|
-
break;
|
|
974
|
-
case keys.SPACE:
|
|
975
|
-
if (this.enableSmartTravel) {
|
|
976
|
-
this.initiateSmartTravel(event);
|
|
977
|
-
}
|
|
978
|
-
break;
|
|
979
|
-
default:
|
|
980
|
-
break;
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
/**
|
|
985
|
-
* Catch and manage the event when the mouse wheel is rolled.
|
|
986
|
-
*
|
|
987
|
-
* @param {Event} event the current event
|
|
988
|
-
* @ignore
|
|
989
|
-
*/
|
|
990
|
-
onMouseWheel(event) {
|
|
991
|
-
if (!this.enabled) {
|
|
992
|
-
return;
|
|
993
|
-
}
|
|
994
|
-
event.preventDefault();
|
|
995
|
-
event.stopPropagation();
|
|
996
|
-
if (STATE.NONE === this.state) {
|
|
997
|
-
this.initiateZoom(event);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
/**
|
|
1002
|
-
* Catch and manage the event when the context menu is called (by a right-click on the window). We use this
|
|
1003
|
-
* to prevent the context menu from appearing so we can use right click for other inputs.
|
|
1004
|
-
*
|
|
1005
|
-
* @param {Event} event the current event
|
|
1006
|
-
* @ignore
|
|
1007
|
-
*/
|
|
1008
|
-
onContextMenu(event) {
|
|
1009
|
-
event.preventDefault();
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
/**
|
|
1013
|
-
* Smoothing function (sigmoid) : based on h01 Hermite function.
|
|
1014
|
-
*
|
|
1015
|
-
* @param {number} value the value to be smoothed, between 0 and 1.
|
|
1016
|
-
* @return {number} a value between 0 and 1.
|
|
1017
|
-
* @ignore
|
|
1018
|
-
*/
|
|
1019
|
-
smooth(value) {
|
|
1020
|
-
// p between 1.0 and 1.5 (empirical)
|
|
1021
|
-
|
|
1022
|
-
return (value ** 2 * (3 - 2 * value)) ** 1.20;
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
export default PlanarControls;
|