easy-three-utils 0.0.1
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/package.json +12 -0
- package/src/common/index.ts +24 -0
- package/src/common/useLine2.ts +87 -0
- package/src/common/useLoader.ts +184 -0
- package/src/common/useLocationCalculator.ts +145 -0
- package/src/common/useMark.ts +42 -0
- package/src/common/useTween.ts +86 -0
- package/src/core/basic/camera.ts +28 -0
- package/src/core/basic/clock.ts +11 -0
- package/src/core/basic/control.ts +32 -0
- package/src/core/basic/index.ts +35 -0
- package/src/core/basic/labelRenderer.ts +26 -0
- package/src/core/basic/light.ts +63 -0
- package/src/core/basic/renderer.ts +37 -0
- package/src/core/basic/scene.ts +11 -0
- package/src/core/basic/stats.ts +16 -0
- package/src/core/event.ts +74 -0
- package/src/core/index.ts +11 -0
- package/src/core/main.ts +389 -0
- package/src/draco/README.md +32 -0
- package/src/draco/draco_decoder.js +34 -0
- package/src/draco/draco_decoder.wasm +0 -0
- package/src/draco/draco_encoder.js +33 -0
- package/src/draco/draco_wasm_wrapper.js +117 -0
- package/src/draco/gltf/draco_decoder.js +33 -0
- package/src/draco/gltf/draco_decoder.wasm +0 -0
- package/src/draco/gltf/draco_encoder.js +33 -0
- package/src/draco/gltf/draco_wasm_wrapper.js +116 -0
- package/src/tileRenderer/base/Tile.d.ts +50 -0
- package/src/tileRenderer/base/TileBase.d.ts +76 -0
- package/src/tileRenderer/base/TileInternal.d.ts +36 -0
- package/src/tileRenderer/base/TilesRendererBase.d.ts +35 -0
- package/src/tileRenderer/base/TilesRendererBase.js +847 -0
- package/src/tileRenderer/base/Tileset.d.ts +66 -0
- package/src/tileRenderer/base/constants.d.ts +6 -0
- package/src/tileRenderer/base/constants.js +16 -0
- package/src/tileRenderer/base/loaders/B3DMLoaderBase.d.ts +18 -0
- package/src/tileRenderer/base/loaders/B3DMLoaderBase.js +85 -0
- package/src/tileRenderer/base/loaders/CMPTLoaderBase.d.ts +22 -0
- package/src/tileRenderer/base/loaders/CMPTLoaderBase.js +61 -0
- package/src/tileRenderer/base/loaders/I3DMLoaderBase.d.ts +21 -0
- package/src/tileRenderer/base/loaders/I3DMLoaderBase.js +130 -0
- package/src/tileRenderer/base/loaders/LoaderBase.d.ts +10 -0
- package/src/tileRenderer/base/loaders/LoaderBase.js +73 -0
- package/src/tileRenderer/base/loaders/PNTSLoaderBase.d.ts +17 -0
- package/src/tileRenderer/base/loaders/PNTSLoaderBase.js +82 -0
- package/src/tileRenderer/base/plugins/ImplicitTilingPlugin.js +12 -0
- package/src/tileRenderer/base/traverseFunctions.js +468 -0
- package/src/tileRenderer/gltf.js +144 -0
- package/src/tileRenderer/index.d.ts +41 -0
- package/src/tileRenderer/index.js +44 -0
- package/src/tileRenderer/plugins/README.md +578 -0
- package/src/tileRenderer/plugins/base/ImplicitTilingPlugin.d.ts +2 -0
- package/src/tileRenderer/plugins/base/ImplicitTilingPlugin.js +84 -0
- package/src/tileRenderer/plugins/base/SUBTREELoader.js +876 -0
- package/src/tileRenderer/plugins/index.d.ts +17 -0
- package/src/tileRenderer/plugins/index.js +17 -0
- package/src/tileRenderer/plugins/three/CesiumIonAuthPlugin.d.ts +9 -0
- package/src/tileRenderer/plugins/three/CesiumIonAuthPlugin.js +175 -0
- package/src/tileRenderer/plugins/three/DebugTilesPlugin.d.ts +29 -0
- package/src/tileRenderer/plugins/three/DebugTilesPlugin.js +677 -0
- package/src/tileRenderer/plugins/three/GLTFExtensionsPlugin.d.ts +18 -0
- package/src/tileRenderer/plugins/three/GLTFExtensionsPlugin.js +86 -0
- package/src/tileRenderer/plugins/three/GoogleAttributionsManager.js +62 -0
- package/src/tileRenderer/plugins/three/GoogleCloudAuthPlugin.d.ts +5 -0
- package/src/tileRenderer/plugins/three/GoogleCloudAuthPlugin.js +200 -0
- package/src/tileRenderer/plugins/three/ReorientationPlugin.d.ts +12 -0
- package/src/tileRenderer/plugins/three/ReorientationPlugin.js +136 -0
- package/src/tileRenderer/plugins/three/TileCompressionPlugin.d.ts +18 -0
- package/src/tileRenderer/plugins/three/TileCompressionPlugin.js +223 -0
- package/src/tileRenderer/plugins/three/UpdateOnChangePlugin.d.ts +5 -0
- package/src/tileRenderer/plugins/three/UpdateOnChangePlugin.js +87 -0
- package/src/tileRenderer/plugins/three/fade/FadeManager.js +370 -0
- package/src/tileRenderer/plugins/three/fade/TilesFadePlugin.d.ts +9 -0
- package/src/tileRenderer/plugins/three/fade/TilesFadePlugin.js +318 -0
- package/src/tileRenderer/plugins/three/gltf/GLTFCesiumRTCExtension.d.ts +5 -0
- package/src/tileRenderer/plugins/three/gltf/GLTFCesiumRTCExtension.js +27 -0
- package/src/tileRenderer/plugins/three/gltf/GLTFMeshFeaturesExtension.d.ts +30 -0
- package/src/tileRenderer/plugins/three/gltf/GLTFMeshFeaturesExtension.js +76 -0
- package/src/tileRenderer/plugins/three/gltf/GLTFStructuralMetadataExtension.d.ts +49 -0
- package/src/tileRenderer/plugins/three/gltf/GLTFStructuralMetadataExtension.js +147 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/classes/ClassProperty.js +149 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/classes/MeshFeatures.js +215 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertyAttributeAccessor.js +107 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertySetAccessor.js +45 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertyTableAccessor.js +209 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertyTextureAccessor.js +244 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/classes/StructuralMetadata.js +202 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/math/Matrix2.js +55 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/utilities/ClassPropertyHelpers.js +495 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/utilities/TexCoordUtilities.js +72 -0
- package/src/tileRenderer/plugins/three/gltf/metadata/utilities/TextureReadUtility.js +154 -0
- package/src/tileRenderer/plugins/three/objects/EllipsoidRegionHelper.js +186 -0
- package/src/tileRenderer/plugins/three/objects/SphereHelper.js +55 -0
- package/src/tileRenderer/r3f/README.md +238 -0
- package/src/tileRenderer/r3f/components/CameraControls.jsx +132 -0
- package/src/tileRenderer/r3f/components/CameraTransition.jsx +177 -0
- package/src/tileRenderer/r3f/components/CanvasDOMOverlay.jsx +54 -0
- package/src/tileRenderer/r3f/components/CompassGizmo.jsx +260 -0
- package/src/tileRenderer/r3f/components/TilesAttributionOverlay.jsx +110 -0
- package/src/tileRenderer/r3f/components/TilesRenderer.jsx +239 -0
- package/src/tileRenderer/r3f/index.jsx +6 -0
- package/src/tileRenderer/r3f/utilities/useForceUpdate.jsx +8 -0
- package/src/tileRenderer/r3f/utilities/useObjectDep.jsx +59 -0
- package/src/tileRenderer/r3f/utilities/useOptions.jsx +143 -0
- package/src/tileRenderer/three/DebugTilesRenderer.d.ts +28 -0
- package/src/tileRenderer/three/DebugTilesRenderer.js +58 -0
- package/src/tileRenderer/three/TilesGroup.d.ts +9 -0
- package/src/tileRenderer/three/TilesGroup.js +91 -0
- package/src/tileRenderer/three/TilesRenderer.d.ts +37 -0
- package/src/tileRenderer/three/TilesRenderer.js +1049 -0
- package/src/tileRenderer/three/controls/CameraTransitionManager.js +305 -0
- package/src/tileRenderer/three/controls/EnvironmentControls.js +1295 -0
- package/src/tileRenderer/three/controls/GlobeControls.js +684 -0
- package/src/tileRenderer/three/controls/PivotPointMesh.js +104 -0
- package/src/tileRenderer/three/controls/PointerTracker.js +257 -0
- package/src/tileRenderer/three/controls/utils.js +113 -0
- package/src/tileRenderer/three/loaders/B3DMLoader.d.ts +26 -0
- package/src/tileRenderer/three/loaders/B3DMLoader.js +85 -0
- package/src/tileRenderer/three/loaders/CMPTLoader.d.ts +19 -0
- package/src/tileRenderer/three/loaders/CMPTLoader.js +97 -0
- package/src/tileRenderer/three/loaders/GLTFExtensionLoader.d.ts +11 -0
- package/src/tileRenderer/three/loaders/GLTFExtensionLoader.js +68 -0
- package/src/tileRenderer/three/loaders/I3DMLoader.d.ts +26 -0
- package/src/tileRenderer/three/loaders/I3DMLoader.js +256 -0
- package/src/tileRenderer/three/loaders/PNTSLoader.d.ts +25 -0
- package/src/tileRenderer/three/loaders/PNTSLoader.js +202 -0
- package/src/tileRenderer/three/loaders/gltf/GLTFCesiumRTCExtension.js +12 -0
- package/src/tileRenderer/three/loaders/gltf/GLTFMeshFeaturesExtension.js +12 -0
- package/src/tileRenderer/three/loaders/gltf/GLTFStructuralMetadataExtension.js +12 -0
- package/src/tileRenderer/three/math/Ellipsoid.d.ts +31 -0
- package/src/tileRenderer/three/math/Ellipsoid.js +337 -0
- package/src/tileRenderer/three/math/EllipsoidRegion.d.ts +23 -0
- package/src/tileRenderer/three/math/EllipsoidRegion.js +178 -0
- package/src/tileRenderer/three/math/ExtendedFrustum.js +65 -0
- package/src/tileRenderer/three/math/GeoConstants.d.ts +4 -0
- package/src/tileRenderer/three/math/GeoConstants.js +5 -0
- package/src/tileRenderer/three/math/GeoUtils.d.ts +9 -0
- package/src/tileRenderer/three/math/GeoUtils.js +106 -0
- package/src/tileRenderer/three/math/OBB.js +179 -0
- package/src/tileRenderer/three/math/TileBoundingVolume.js +272 -0
- package/src/tileRenderer/three/plugins/CesiumIonAuthPlugin.js +12 -0
- package/src/tileRenderer/three/plugins/DebugTilesPlugin.js +26 -0
- package/src/tileRenderer/three/plugins/GoogleCloudAuthPlugin.js +12 -0
- package/src/tileRenderer/three/raycastTraverse.js +178 -0
- package/src/tileRenderer/three/renderers/CesiumIonTilesRenderer.d.ts +14 -0
- package/src/tileRenderer/three/renderers/CesiumIonTilesRenderer.js +21 -0
- package/src/tileRenderer/three/renderers/GoogleTilesRenderer.d.ts +43 -0
- package/src/tileRenderer/three/renderers/GoogleTilesRenderer.js +48 -0
- package/src/tileRenderer/three/utilities.js +54 -0
- package/src/tileRenderer/utilities/BatchTable.d.ts +24 -0
- package/src/tileRenderer/utilities/BatchTable.js +82 -0
- package/src/tileRenderer/utilities/BatchTableHierarchyExtension.js +127 -0
- package/src/tileRenderer/utilities/FeatureTable.d.ts +30 -0
- package/src/tileRenderer/utilities/FeatureTable.js +159 -0
- package/src/tileRenderer/utilities/LRUCache.d.ts +8 -0
- package/src/tileRenderer/utilities/LRUCache.js +385 -0
- package/src/tileRenderer/utilities/PriorityQueue.d.ts +16 -0
- package/src/tileRenderer/utilities/PriorityQueue.js +137 -0
- package/src/tileRenderer/utilities/arrayToString.js +7 -0
- package/src/tileRenderer/utilities/readMagicBytes.js +29 -0
- package/src/tileRenderer/utilities/rgb565torgb.js +22 -0
- package/src/tileRenderer/utilities/urlExtension.js +34 -0
- package/tsconfig.json +42 -0
- package/tsconfig.node.json +11 -0
- package/typings/three.d.ts +27 -0
|
@@ -0,0 +1,684 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Matrix4,
|
|
3
|
+
Quaternion,
|
|
4
|
+
Vector2,
|
|
5
|
+
Vector3,
|
|
6
|
+
MathUtils,
|
|
7
|
+
Ray,
|
|
8
|
+
} from 'three';
|
|
9
|
+
import { DRAG, EnvironmentControls, NONE } from './EnvironmentControls.js';
|
|
10
|
+
import { closestRayEllipsoidSurfacePointEstimate, closestRaySpherePointFromRotation, makeRotateAroundPoint, mouseToCoords, setRaycasterFromCamera } from './utils.js';
|
|
11
|
+
import { Ellipsoid } from '../math/Ellipsoid.js';
|
|
12
|
+
|
|
13
|
+
const _invMatrix = new Matrix4();
|
|
14
|
+
const _rotMatrix = new Matrix4();
|
|
15
|
+
const _pos = new Vector3();
|
|
16
|
+
const _vec = new Vector3();
|
|
17
|
+
const _center = new Vector3();
|
|
18
|
+
const _forward = new Vector3();
|
|
19
|
+
const _right = new Vector3();
|
|
20
|
+
const _targetRight = new Vector3();
|
|
21
|
+
const _globalUp = new Vector3();
|
|
22
|
+
const _quaternion = new Quaternion();
|
|
23
|
+
const _zoomPointUp = new Vector3();
|
|
24
|
+
const _toCenter = new Vector3();
|
|
25
|
+
const _latLon = {};
|
|
26
|
+
const _ray = new Ray();
|
|
27
|
+
const _ellipsoid = new Ellipsoid();
|
|
28
|
+
|
|
29
|
+
const _pointer = new Vector2();
|
|
30
|
+
const MIN_ELEVATION = 400;
|
|
31
|
+
|
|
32
|
+
export class GlobeControls extends EnvironmentControls {
|
|
33
|
+
|
|
34
|
+
get ellipsoid() {
|
|
35
|
+
|
|
36
|
+
return this.tilesRenderer ? this.tilesRenderer.ellipsoid : null;
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get tilesGroup() {
|
|
41
|
+
|
|
42
|
+
return this.tilesRenderer ? this.tilesRenderer.group : null;
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
constructor( scene = null, camera = null, domElement = null, tilesRenderer = null ) {
|
|
47
|
+
|
|
48
|
+
// store which mode the drag stats are in
|
|
49
|
+
super( scene, camera, domElement );
|
|
50
|
+
|
|
51
|
+
this.isGlobeControls = true;
|
|
52
|
+
|
|
53
|
+
this._dragMode = 0;
|
|
54
|
+
this._rotationMode = 0;
|
|
55
|
+
this.maxZoom = 0.01;
|
|
56
|
+
this.useFallbackPlane = false;
|
|
57
|
+
this.reorientOnDrag = false;
|
|
58
|
+
|
|
59
|
+
this.dragQuaternion = new Quaternion();
|
|
60
|
+
|
|
61
|
+
this.setTilesRenderer( tilesRenderer );
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setScene( scene ) {
|
|
66
|
+
|
|
67
|
+
if ( scene === null && this.tilesRenderer !== null ) {
|
|
68
|
+
|
|
69
|
+
super.setScene( this.tilesRenderer.group );
|
|
70
|
+
|
|
71
|
+
} else {
|
|
72
|
+
|
|
73
|
+
super.setScene( scene );
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
getPivotPoint( target ) {
|
|
80
|
+
|
|
81
|
+
const { camera, tilesGroup, ellipsoid } = this;
|
|
82
|
+
|
|
83
|
+
// get camera values
|
|
84
|
+
_forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
|
|
85
|
+
_invMatrix.copy( tilesGroup.matrixWorld ).invert();
|
|
86
|
+
|
|
87
|
+
// set a ray in the local ellipsoid frame
|
|
88
|
+
_ray.origin.copy( camera.position );
|
|
89
|
+
_ray.direction.copy( _forward );
|
|
90
|
+
_ray.applyMatrix4( _invMatrix );
|
|
91
|
+
|
|
92
|
+
// get the estimated closest point
|
|
93
|
+
closestRayEllipsoidSurfacePointEstimate( _ray, ellipsoid, _vec );
|
|
94
|
+
_vec.applyMatrix4( tilesGroup.matrixWorld );
|
|
95
|
+
|
|
96
|
+
// use the closest point if no pivot was provided or it's closer
|
|
97
|
+
if (
|
|
98
|
+
super.getPivotPoint( target ) === null ||
|
|
99
|
+
target.distanceTo( _ray.origin ) > _vec.distanceTo( _ray.origin )
|
|
100
|
+
) {
|
|
101
|
+
|
|
102
|
+
target.copy( _vec );
|
|
103
|
+
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return target;
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// get the vector to the center of the provided globe
|
|
111
|
+
getVectorToCenter( target ) {
|
|
112
|
+
|
|
113
|
+
const { tilesGroup, camera } = this;
|
|
114
|
+
return target
|
|
115
|
+
.setFromMatrixPosition( tilesGroup.matrixWorld )
|
|
116
|
+
.sub( camera.position );
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// get the distance to the center of the globe
|
|
121
|
+
getDistanceToCenter() {
|
|
122
|
+
|
|
123
|
+
return this
|
|
124
|
+
.getVectorToCenter( _vec )
|
|
125
|
+
.length();
|
|
126
|
+
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
getUpDirection( point, target ) {
|
|
130
|
+
|
|
131
|
+
// get the "up" direction based on the wgs84 ellipsoid
|
|
132
|
+
const { tilesGroup, ellipsoid } = this;
|
|
133
|
+
_invMatrix.copy( tilesGroup.matrixWorld ).invert();
|
|
134
|
+
_vec.copy( point ).applyMatrix4( _invMatrix );
|
|
135
|
+
|
|
136
|
+
ellipsoid.getPositionToNormal( _vec, target );
|
|
137
|
+
target.transformDirection( tilesGroup.matrixWorld );
|
|
138
|
+
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
getCameraUpDirection( target ) {
|
|
142
|
+
|
|
143
|
+
const { tilesGroup, ellipsoid, camera } = this;
|
|
144
|
+
if ( camera.isOrthographicCamera ) {
|
|
145
|
+
|
|
146
|
+
this._getVirtualOrthoCameraPosition( _vec );
|
|
147
|
+
|
|
148
|
+
_invMatrix.copy( tilesGroup.matrixWorld ).invert();
|
|
149
|
+
_vec.applyMatrix4( _invMatrix );
|
|
150
|
+
|
|
151
|
+
ellipsoid.getPositionToNormal( _vec, target );
|
|
152
|
+
target.transformDirection( tilesGroup.matrixWorld );
|
|
153
|
+
|
|
154
|
+
} else {
|
|
155
|
+
|
|
156
|
+
this.getUpDirection( camera.position, target );
|
|
157
|
+
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
update( deltaTime = Math.min( this.clock.getDelta(), 64 / 1000 ) ) {
|
|
163
|
+
|
|
164
|
+
if ( ! this.enabled || ! this.tilesGroup || ! this.camera || deltaTime === 0 ) {
|
|
165
|
+
|
|
166
|
+
return;
|
|
167
|
+
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const { camera, pivotMesh } = this;
|
|
171
|
+
|
|
172
|
+
// if we're outside the transition threshold then we toggle some reorientation behavior
|
|
173
|
+
// when adjusting the up frame while moving the camera
|
|
174
|
+
if ( this._isNearControls() ) {
|
|
175
|
+
|
|
176
|
+
this.scaleZoomOrientationAtEdges = this.zoomDelta < 0;
|
|
177
|
+
|
|
178
|
+
} else {
|
|
179
|
+
|
|
180
|
+
if ( this.state !== NONE && this._dragMode !== 1 && this._rotationMode !== 1 ) {
|
|
181
|
+
|
|
182
|
+
pivotMesh.visible = false;
|
|
183
|
+
|
|
184
|
+
}
|
|
185
|
+
this.scaleZoomOrientationAtEdges = false;
|
|
186
|
+
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// fire basic controls update
|
|
190
|
+
super.update( deltaTime );
|
|
191
|
+
|
|
192
|
+
// update the camera planes and the ortho camera position
|
|
193
|
+
this.adjustCamera( camera );
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Updates the passed camera near and far clip planes to encapsulate the ellipsoid from the
|
|
198
|
+
// current position in addition to adjusting the height.
|
|
199
|
+
adjustCamera( camera ) {
|
|
200
|
+
|
|
201
|
+
super.adjustCamera( camera );
|
|
202
|
+
|
|
203
|
+
const { tilesGroup, ellipsoid } = this;
|
|
204
|
+
if ( camera.isPerspectiveCamera ) {
|
|
205
|
+
|
|
206
|
+
// adjust the clip planes
|
|
207
|
+
const distanceToCenter = _vec
|
|
208
|
+
.setFromMatrixPosition( tilesGroup.matrixWorld )
|
|
209
|
+
.sub( camera.position ).length();
|
|
210
|
+
|
|
211
|
+
// update the projection matrix
|
|
212
|
+
// interpolate from the 25% radius margin around the globe down to the surface
|
|
213
|
+
// so we can avoid z fighting when near value is too far at a high altitude
|
|
214
|
+
const largestDistance = Math.max( ...ellipsoid.radius );
|
|
215
|
+
const margin = 0.25 * largestDistance;
|
|
216
|
+
const alpha = MathUtils.clamp( ( distanceToCenter - largestDistance ) / margin, 0, 1 );
|
|
217
|
+
const minNear = MathUtils.lerp( 1, 1000, alpha );
|
|
218
|
+
camera.near = Math.max( minNear, distanceToCenter - largestDistance - margin );
|
|
219
|
+
|
|
220
|
+
// update the far plane to the horizon distance
|
|
221
|
+
const invMatrix = _invMatrix.copy( tilesGroup.matrixWorld ).invert();
|
|
222
|
+
_pos.copy( camera.position ).applyMatrix4( invMatrix );
|
|
223
|
+
ellipsoid.getPositionToCartographic( _pos, _latLon );
|
|
224
|
+
|
|
225
|
+
// use a minimum elevation for computing the horizon distance to avoid the far clip
|
|
226
|
+
// plane approaching zero as the camera goes to or below sea level.
|
|
227
|
+
const elevation = Math.max( ellipsoid.getPositionElevation( _pos ), MIN_ELEVATION );
|
|
228
|
+
const horizonDistance = ellipsoid.calculateHorizonDistance( _latLon.lat, elevation );
|
|
229
|
+
|
|
230
|
+
// extend the horizon distance by 2.5 to handle cases where geometry extends above the horizon
|
|
231
|
+
camera.far = horizonDistance * 2.5 + 0.1;
|
|
232
|
+
camera.updateProjectionMatrix();
|
|
233
|
+
|
|
234
|
+
} else {
|
|
235
|
+
|
|
236
|
+
this._getVirtualOrthoCameraPosition( camera.position, camera );
|
|
237
|
+
camera.updateMatrixWorld();
|
|
238
|
+
|
|
239
|
+
_invMatrix.copy( camera.matrixWorld ).invert();
|
|
240
|
+
_vec.setFromMatrixPosition( tilesGroup.matrixWorld ).applyMatrix4( _invMatrix );
|
|
241
|
+
|
|
242
|
+
const distanceToCenter = - _vec.z;
|
|
243
|
+
camera.near = distanceToCenter - Math.max( ...ellipsoid.radius ) * 1.1;
|
|
244
|
+
camera.far = distanceToCenter + 0.1;
|
|
245
|
+
|
|
246
|
+
// adjust the position of the ortho camera such that the near value is 0
|
|
247
|
+
camera.position.addScaledVector( _forward, camera.near );
|
|
248
|
+
camera.far -= camera.near;
|
|
249
|
+
camera.near = 0;
|
|
250
|
+
|
|
251
|
+
camera.updateProjectionMatrix();
|
|
252
|
+
camera.updateMatrixWorld();
|
|
253
|
+
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// resets the "stuck" drag modes
|
|
259
|
+
resetState() {
|
|
260
|
+
|
|
261
|
+
super.resetState();
|
|
262
|
+
this._dragMode = 0;
|
|
263
|
+
this._rotationMode = 0;
|
|
264
|
+
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
_updatePosition( deltaTime ) {
|
|
268
|
+
|
|
269
|
+
if ( this.state !== DRAG ) {
|
|
270
|
+
|
|
271
|
+
const {
|
|
272
|
+
enableDamping,
|
|
273
|
+
tilesGroup,
|
|
274
|
+
dragQuaternion,
|
|
275
|
+
dragInertia,
|
|
276
|
+
camera,
|
|
277
|
+
} = this;
|
|
278
|
+
|
|
279
|
+
// apply inertia for movement
|
|
280
|
+
if ( enableDamping ) {
|
|
281
|
+
|
|
282
|
+
// ensure our w component is non-one if the xyz values are
|
|
283
|
+
// non zero to ensure we can animate
|
|
284
|
+
if (
|
|
285
|
+
dragQuaternion.w === 1 && (
|
|
286
|
+
dragQuaternion.x !== 0 ||
|
|
287
|
+
dragQuaternion.y !== 0 ||
|
|
288
|
+
dragQuaternion.z !== 0
|
|
289
|
+
)
|
|
290
|
+
) {
|
|
291
|
+
|
|
292
|
+
dragQuaternion.w = Math.min( dragQuaternion.w, 1 - 1e-9 );
|
|
293
|
+
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// construct the rotation matrix
|
|
297
|
+
_center.setFromMatrixPosition( tilesGroup.matrixWorld );
|
|
298
|
+
_quaternion.identity().slerp( dragQuaternion, dragInertia.x * deltaTime );
|
|
299
|
+
makeRotateAroundPoint( _center, _quaternion, _rotMatrix );
|
|
300
|
+
|
|
301
|
+
// apply the rotation
|
|
302
|
+
camera.matrixWorld.premultiply( _rotMatrix );
|
|
303
|
+
camera.matrixWorld.decompose( camera.position, camera.quaternion, _vec );
|
|
304
|
+
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
} else {
|
|
308
|
+
|
|
309
|
+
// save the drag mode state so we can update the pivot mesh visuals in "update"
|
|
310
|
+
if ( this._dragMode === 0 ) {
|
|
311
|
+
|
|
312
|
+
this._dragMode = this._isNearControls() ? 1 : - 1;
|
|
313
|
+
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const {
|
|
317
|
+
raycaster,
|
|
318
|
+
camera,
|
|
319
|
+
pivotPoint,
|
|
320
|
+
pointerTracker,
|
|
321
|
+
domElement,
|
|
322
|
+
tilesGroup,
|
|
323
|
+
} = this;
|
|
324
|
+
|
|
325
|
+
// reuse cache variables
|
|
326
|
+
const pivotDir = _pos;
|
|
327
|
+
const newPivotDir = _targetRight;
|
|
328
|
+
|
|
329
|
+
// get the pointer and ray
|
|
330
|
+
pointerTracker.getCenterPoint( _pointer );
|
|
331
|
+
mouseToCoords( _pointer.x, _pointer.y, domElement, _pointer );
|
|
332
|
+
setRaycasterFromCamera( raycaster, _pointer, camera );
|
|
333
|
+
|
|
334
|
+
// transform to ellipsoid frame
|
|
335
|
+
_invMatrix.copy( tilesGroup.matrixWorld ).invert();
|
|
336
|
+
raycaster.ray.applyMatrix4( _invMatrix );
|
|
337
|
+
|
|
338
|
+
// construct an ellipsoid that matches a sphere with the radius of the globe so
|
|
339
|
+
// the drag position matches where the initial click was
|
|
340
|
+
const pivotRadius = _vec.copy( pivotPoint ).applyMatrix4( _invMatrix ).length();
|
|
341
|
+
_ellipsoid.radius.setScalar( pivotRadius );
|
|
342
|
+
|
|
343
|
+
// find the hit point and use the closest point on the horizon if we miss
|
|
344
|
+
if ( camera.isPerspectiveCamera ) {
|
|
345
|
+
|
|
346
|
+
if ( ! _ellipsoid.intersectRay( raycaster.ray, _vec ) ) {
|
|
347
|
+
|
|
348
|
+
closestRaySpherePointFromRotation( raycaster.ray, pivotRadius, _vec );
|
|
349
|
+
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
} else {
|
|
353
|
+
|
|
354
|
+
closestRayEllipsoidSurfacePointEstimate( raycaster.ray, _ellipsoid, _vec );
|
|
355
|
+
|
|
356
|
+
}
|
|
357
|
+
_vec.applyMatrix4( tilesGroup.matrixWorld );
|
|
358
|
+
|
|
359
|
+
// get the point directions
|
|
360
|
+
_center.setFromMatrixPosition( tilesGroup.matrixWorld );
|
|
361
|
+
pivotDir.subVectors( pivotPoint, _center ).normalize();
|
|
362
|
+
newPivotDir.subVectors( _vec, _center ).normalize();
|
|
363
|
+
|
|
364
|
+
// construct the rotation
|
|
365
|
+
_quaternion.setFromUnitVectors( newPivotDir, pivotDir );
|
|
366
|
+
makeRotateAroundPoint( _center, _quaternion, _rotMatrix );
|
|
367
|
+
|
|
368
|
+
// apply the rotation
|
|
369
|
+
camera.matrixWorld.premultiply( _rotMatrix );
|
|
370
|
+
camera.matrixWorld.decompose( camera.position, camera.quaternion, _vec );
|
|
371
|
+
|
|
372
|
+
const { dragInertia, dragQuaternion } = this;
|
|
373
|
+
if ( pointerTracker.getMoveDistance() / deltaTime < 2 * window.devicePixelRatio ) {
|
|
374
|
+
|
|
375
|
+
dragQuaternion.slerp( _quaternion, 0.5 );
|
|
376
|
+
dragInertia.set( 1 / deltaTime, 0, 0 );
|
|
377
|
+
|
|
378
|
+
} else {
|
|
379
|
+
|
|
380
|
+
dragQuaternion.copy( _quaternion );
|
|
381
|
+
dragInertia.set( 1 / deltaTime, 0, 0 );
|
|
382
|
+
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
this._alignCameraUp( this.up );
|
|
388
|
+
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// disable rotation once we're outside the control transition
|
|
392
|
+
_updateRotation( ...args ) {
|
|
393
|
+
|
|
394
|
+
if ( this._rotationMode === 1 || this._isNearControls() ) {
|
|
395
|
+
|
|
396
|
+
this._rotationMode = 1;
|
|
397
|
+
super._updateRotation( ...args );
|
|
398
|
+
|
|
399
|
+
} else {
|
|
400
|
+
|
|
401
|
+
this.pivotMesh.visible = false;
|
|
402
|
+
this._rotationMode = - 1;
|
|
403
|
+
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
this._alignCameraUp( this.up );
|
|
407
|
+
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
_updateZoom() {
|
|
411
|
+
|
|
412
|
+
const { zoomDelta, ellipsoid, zoomSpeed, zoomPoint, camera, maxZoom } = this;
|
|
413
|
+
|
|
414
|
+
// used to scale the tilt transitions based on zoom intensity
|
|
415
|
+
const deltaAlpha = MathUtils.clamp( MathUtils.mapLinear( Math.abs( zoomDelta ), 0, 20, 0, 1 ), 0, 1 );
|
|
416
|
+
if ( this._isNearControls() || zoomDelta > 0 ) {
|
|
417
|
+
|
|
418
|
+
this._updateZoomDirection();
|
|
419
|
+
|
|
420
|
+
// When zooming try to tilt the camera towards the center of the planet to avoid the globe
|
|
421
|
+
// spinning as you zoom out from the horizon
|
|
422
|
+
if ( zoomDelta < 0 && ( this.zoomPointSet || this._updateZoomPoint() ) ) {
|
|
423
|
+
|
|
424
|
+
// get the forward vector and vector toward the center of the ellipsoid
|
|
425
|
+
_forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ).normalize();
|
|
426
|
+
_toCenter.copy( this.up ).multiplyScalar( - 1 );
|
|
427
|
+
|
|
428
|
+
// Calculate alpha values to use to scale the amount of tilt that occurs as the camera moves.
|
|
429
|
+
// Scales based on mouse position near the horizon and current tilt.
|
|
430
|
+
this.getUpDirection( zoomPoint, _zoomPointUp );
|
|
431
|
+
const upAlpha = MathUtils.clamp( MathUtils.mapLinear( - _zoomPointUp.dot( _toCenter ), 1, 0.95, 0, 1 ), 0, 1 );
|
|
432
|
+
const forwardAlpha = 1 - _forward.dot( _toCenter );
|
|
433
|
+
const cameraAlpha = camera.isOrthographicCamera ? 0.05 : 1;
|
|
434
|
+
const adjustedDeltaAlpha = MathUtils.clamp( deltaAlpha * 3, 0, 1 );
|
|
435
|
+
|
|
436
|
+
// apply scale
|
|
437
|
+
const alpha = Math.min( upAlpha * forwardAlpha * cameraAlpha * adjustedDeltaAlpha, 0.1 );
|
|
438
|
+
_toCenter.lerpVectors( _forward, _toCenter, alpha ).normalize();
|
|
439
|
+
|
|
440
|
+
// perform rotation
|
|
441
|
+
_quaternion.setFromUnitVectors( _forward, _toCenter );
|
|
442
|
+
makeRotateAroundPoint( zoomPoint, _quaternion, _rotMatrix );
|
|
443
|
+
camera.matrixWorld.premultiply( _rotMatrix );
|
|
444
|
+
camera.matrixWorld.decompose( camera.position, camera.quaternion, _toCenter );
|
|
445
|
+
|
|
446
|
+
// update zoom direction
|
|
447
|
+
this.zoomDirection.subVectors( zoomPoint, camera.position ).normalize();
|
|
448
|
+
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
super._updateZoom();
|
|
452
|
+
|
|
453
|
+
} else if ( camera.isPerspectiveCamera ) {
|
|
454
|
+
|
|
455
|
+
// orient the camera to focus on the earth during the zoom
|
|
456
|
+
const transitionDistance = this._getPerspectiveTransitionDistance();
|
|
457
|
+
const maxDistance = this._getMaxPerspectiveDistance();
|
|
458
|
+
const distanceAlpha = MathUtils.mapLinear( this.getDistanceToCenter(), transitionDistance, maxDistance, 0, 1 );
|
|
459
|
+
this._tiltTowardsCenter( MathUtils.lerp( 0, 0.4, distanceAlpha * deltaAlpha ) );
|
|
460
|
+
this._alignCameraUpToNorth( MathUtils.lerp( 0, 0.2, distanceAlpha * deltaAlpha ) );
|
|
461
|
+
|
|
462
|
+
// calculate zoom in a similar way to environment controls so
|
|
463
|
+
// the zoom speeds are comparable
|
|
464
|
+
const dist = this.getDistanceToCenter() - ellipsoid.radius.x;
|
|
465
|
+
const scale = zoomDelta * dist * zoomSpeed * 0.0025;
|
|
466
|
+
const clampedScale = Math.max( scale, Math.min( this.getDistanceToCenter() - maxDistance, 0 ) );
|
|
467
|
+
|
|
468
|
+
// zoom out directly from the globe center
|
|
469
|
+
this.getVectorToCenter( _vec ).normalize();
|
|
470
|
+
this.camera.position.addScaledVector( _vec, clampedScale );
|
|
471
|
+
this.camera.updateMatrixWorld();
|
|
472
|
+
|
|
473
|
+
this.zoomDelta = 0;
|
|
474
|
+
|
|
475
|
+
} else {
|
|
476
|
+
|
|
477
|
+
const transitionZoom = this._getOrthographicTransitionZoom();
|
|
478
|
+
const minZoom = this._getMinOrthographicZoom();
|
|
479
|
+
const distanceAlpha = MathUtils.mapLinear( camera.zoom, transitionZoom, minZoom, 0, 1 );
|
|
480
|
+
this._tiltTowardsCenter( MathUtils.lerp( 0, 0.4, distanceAlpha * deltaAlpha ) );
|
|
481
|
+
this._alignCameraUpToNorth( MathUtils.lerp( 0, 0.2, distanceAlpha * deltaAlpha ) );
|
|
482
|
+
|
|
483
|
+
const scale = this.zoomDelta;
|
|
484
|
+
const normalizedDelta = Math.pow( 0.95, Math.abs( scale * 0.05 ) );
|
|
485
|
+
const scaleFactor = scale > 0 ? 1 / Math.abs( normalizedDelta ) : normalizedDelta;
|
|
486
|
+
|
|
487
|
+
const maxScaleFactor = minZoom / camera.zoom;
|
|
488
|
+
const clampedScaleFactor = Math.max( scaleFactor * zoomSpeed, Math.min( maxScaleFactor, 1 ) );
|
|
489
|
+
|
|
490
|
+
camera.zoom = Math.min( maxZoom, camera.zoom * clampedScaleFactor );
|
|
491
|
+
camera.updateProjectionMatrix();
|
|
492
|
+
|
|
493
|
+
this.zoomDelta = 0;
|
|
494
|
+
this.zoomDirectionSet = false;
|
|
495
|
+
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// tilt the camera to align with north
|
|
501
|
+
_alignCameraUpToNorth( alpha ) {
|
|
502
|
+
|
|
503
|
+
const { tilesGroup } = this;
|
|
504
|
+
_globalUp.set( 0, 0, 1 ).transformDirection( tilesGroup.matrixWorld );
|
|
505
|
+
this._alignCameraUp( _globalUp, alpha );
|
|
506
|
+
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// tilt the camera to align with the provided "up" value
|
|
510
|
+
_alignCameraUp( up, alpha = null ) {
|
|
511
|
+
|
|
512
|
+
const { camera } = this;
|
|
513
|
+
_forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
|
|
514
|
+
_right.set( - 1, 0, 0 ).transformDirection( camera.matrixWorld );
|
|
515
|
+
_targetRight.crossVectors( up, _forward );
|
|
516
|
+
|
|
517
|
+
// compute the alpha based on how far away from boresight the up vector is
|
|
518
|
+
// so we can ease into the correct orientation
|
|
519
|
+
if ( alpha === null ) {
|
|
520
|
+
|
|
521
|
+
alpha = 1 - Math.abs( _forward.dot( up ) );
|
|
522
|
+
alpha = MathUtils.mapLinear( alpha, 0, 1, - 0.01, 1 );
|
|
523
|
+
alpha = MathUtils.clamp( alpha, 0, 1 ) ** 2;
|
|
524
|
+
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
_targetRight.lerp( _right, 1 - alpha ).normalize();
|
|
528
|
+
|
|
529
|
+
_quaternion.setFromUnitVectors( _right, _targetRight );
|
|
530
|
+
camera.quaternion.premultiply( _quaternion );
|
|
531
|
+
camera.updateMatrixWorld();
|
|
532
|
+
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// tilt the camera to look at the center of the globe
|
|
536
|
+
_tiltTowardsCenter( alpha ) {
|
|
537
|
+
|
|
538
|
+
const {
|
|
539
|
+
camera,
|
|
540
|
+
tilesGroup,
|
|
541
|
+
} = this;
|
|
542
|
+
|
|
543
|
+
_forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ).normalize();
|
|
544
|
+
_vec.setFromMatrixPosition( tilesGroup.matrixWorld ).sub( camera.position ).normalize();
|
|
545
|
+
_vec.lerp( _forward, 1 - alpha ).normalize();
|
|
546
|
+
|
|
547
|
+
_quaternion.setFromUnitVectors( _forward, _vec );
|
|
548
|
+
camera.quaternion.premultiply( _quaternion );
|
|
549
|
+
camera.updateMatrixWorld();
|
|
550
|
+
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// returns the perspective camera transition distance can move to based on globe size and fov
|
|
554
|
+
_getPerspectiveTransitionDistance() {
|
|
555
|
+
|
|
556
|
+
const { camera, ellipsoid } = this;
|
|
557
|
+
if ( ! camera.isPerspectiveCamera ) {
|
|
558
|
+
|
|
559
|
+
throw new Error();
|
|
560
|
+
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// When the smallest fov spans 65% of the ellipsoid then we use the near controls
|
|
564
|
+
const ellipsoidRadius = Math.max( ...ellipsoid.radius );
|
|
565
|
+
const fovHoriz = 2 * Math.atan( Math.tan( MathUtils.DEG2RAD * camera.fov * 0.5 ) * camera.aspect );
|
|
566
|
+
const distVert = ellipsoidRadius / Math.tan( MathUtils.DEG2RAD * camera.fov * 0.5 );
|
|
567
|
+
const distHoriz = ellipsoidRadius / Math.tan( fovHoriz * 0.5 );
|
|
568
|
+
const dist = Math.max( distVert, distHoriz );
|
|
569
|
+
|
|
570
|
+
return dist;
|
|
571
|
+
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// returns the max distance the perspective camera can move to based on globe size and fov
|
|
575
|
+
_getMaxPerspectiveDistance() {
|
|
576
|
+
|
|
577
|
+
const { camera, ellipsoid } = this;
|
|
578
|
+
if ( ! camera.isPerspectiveCamera ) {
|
|
579
|
+
|
|
580
|
+
throw new Error();
|
|
581
|
+
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// allow for zooming out such that the ellipsoid is half the size of the largest fov
|
|
585
|
+
const ellipsoidRadius = Math.max( ...ellipsoid.radius );
|
|
586
|
+
const fovHoriz = 2 * Math.atan( Math.tan( MathUtils.DEG2RAD * camera.fov * 0.5 ) * camera.aspect );
|
|
587
|
+
const distVert = ellipsoidRadius / Math.tan( MathUtils.DEG2RAD * camera.fov * 0.5 );
|
|
588
|
+
const distHoriz = ellipsoidRadius / Math.tan( fovHoriz * 0.5 );
|
|
589
|
+
const dist = 2 * Math.max( distVert, distHoriz );
|
|
590
|
+
|
|
591
|
+
return dist;
|
|
592
|
+
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
// returns the transition threshold for orthographic zoom based on the globe size and camera settings
|
|
596
|
+
_getOrthographicTransitionZoom() {
|
|
597
|
+
|
|
598
|
+
const { camera, ellipsoid } = this;
|
|
599
|
+
if ( ! camera.isOrthographicCamera ) {
|
|
600
|
+
|
|
601
|
+
throw new Error();
|
|
602
|
+
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const orthoHeight = ( camera.top - camera.bottom );
|
|
606
|
+
const orthoWidth = ( camera.right - camera.left );
|
|
607
|
+
const orthoSize = Math.max( orthoHeight, orthoWidth );
|
|
608
|
+
const ellipsoidRadius = Math.max( ...ellipsoid.radius );
|
|
609
|
+
const ellipsoidDiameter = 2 * ellipsoidRadius;
|
|
610
|
+
return 2 * orthoSize / ellipsoidDiameter;
|
|
611
|
+
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// returns the minimum allowed orthographic zoom based on the globe size and camera settings
|
|
615
|
+
_getMinOrthographicZoom() {
|
|
616
|
+
|
|
617
|
+
const { camera, ellipsoid } = this;
|
|
618
|
+
if ( ! camera.isOrthographicCamera ) {
|
|
619
|
+
|
|
620
|
+
throw new Error();
|
|
621
|
+
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
const orthoHeight = ( camera.top - camera.bottom );
|
|
625
|
+
const orthoWidth = ( camera.right - camera.left );
|
|
626
|
+
const orthoSize = Math.min( orthoHeight, orthoWidth );
|
|
627
|
+
const ellipsoidRadius = Math.max( ...ellipsoid.radius );
|
|
628
|
+
const ellipsoidDiameter = 2 * ellipsoidRadius;
|
|
629
|
+
return 0.7 * orthoSize / ellipsoidDiameter;
|
|
630
|
+
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// returns the "virtual position" of the orthographic based on where it is and
|
|
634
|
+
// where it's looking primarily so we can reasonably position the camera object
|
|
635
|
+
// in space and derive a reasonable "up" value.
|
|
636
|
+
_getVirtualOrthoCameraPosition( target, camera = this.camera ) {
|
|
637
|
+
|
|
638
|
+
const { tilesGroup, ellipsoid } = this;
|
|
639
|
+
if ( ! camera.isOrthographicCamera ) {
|
|
640
|
+
|
|
641
|
+
throw new Error();
|
|
642
|
+
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
_invMatrix.copy( tilesGroup.matrixWorld ).invert();
|
|
646
|
+
|
|
647
|
+
// get ray in globe coordinate frame
|
|
648
|
+
_ray.origin.copy( camera.position );
|
|
649
|
+
_ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
|
|
650
|
+
_ray.applyMatrix4( _invMatrix );
|
|
651
|
+
|
|
652
|
+
// get the closest point to the ray on the globe in the global coordinate frame
|
|
653
|
+
closestRayEllipsoidSurfacePointEstimate( _ray, ellipsoid, _pos );
|
|
654
|
+
_pos.applyMatrix4( tilesGroup.matrixWorld );
|
|
655
|
+
|
|
656
|
+
// get ortho camera info
|
|
657
|
+
const orthoHeight = ( camera.top - camera.bottom );
|
|
658
|
+
const orthoWidth = ( camera.right - camera.left );
|
|
659
|
+
const orthoSize = Math.max( orthoHeight, orthoWidth ) / camera.zoom;
|
|
660
|
+
_forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
|
|
661
|
+
|
|
662
|
+
// ensure we move the camera exactly along the forward vector to avoid shifting
|
|
663
|
+
// the camera in other directions due to floating point error
|
|
664
|
+
const dist = _pos.sub( camera.position ).dot( _forward );
|
|
665
|
+
target.copy( camera.position ).addScaledVector( _forward, dist - orthoSize * 4 );
|
|
666
|
+
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
_isNearControls() {
|
|
670
|
+
|
|
671
|
+
const { camera } = this;
|
|
672
|
+
if ( camera.isPerspectiveCamera ) {
|
|
673
|
+
|
|
674
|
+
return this.getDistanceToCenter() < this._getPerspectiveTransitionDistance();
|
|
675
|
+
|
|
676
|
+
} else {
|
|
677
|
+
|
|
678
|
+
return camera.zoom > this._getOrthographicTransitionZoom();
|
|
679
|
+
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
}
|