@onerjs/core 8.31.6 → 8.31.7
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/Animations/animation.d.ts +2 -1
- package/Animations/animation.js +3 -2
- package/Animations/animation.js.map +1 -1
- package/Behaviors/Cameras/interpolatingBehavior.d.ts +2 -1
- package/Behaviors/Cameras/interpolatingBehavior.js +2 -2
- package/Behaviors/Cameras/interpolatingBehavior.js.map +1 -1
- package/Cameras/geospatialCamera.d.ts +12 -3
- package/Cameras/geospatialCamera.js +91 -36
- package/Cameras/geospatialCamera.js.map +1 -1
- package/Cameras/geospatialCameraMovement.d.ts +6 -2
- package/Cameras/geospatialCameraMovement.js +10 -10
- package/Cameras/geospatialCameraMovement.js.map +1 -1
- package/Engines/abstractEngine.js +2 -2
- package/Engines/abstractEngine.js.map +1 -1
- package/Engines/thinEngine.js +1 -1
- package/Engines/thinEngine.js.map +1 -1
- package/FrameGraph/Node/nodeRenderGraph.d.ts +22 -5
- package/FrameGraph/Node/nodeRenderGraph.js +39 -18
- package/FrameGraph/Node/nodeRenderGraph.js.map +1 -1
- package/FrameGraph/Passes/pass.d.ts +2 -0
- package/FrameGraph/Passes/pass.js +2 -0
- package/FrameGraph/Passes/pass.js.map +1 -1
- package/FrameGraph/Passes/renderPass.d.ts +2 -0
- package/FrameGraph/Passes/renderPass.js +4 -0
- package/FrameGraph/Passes/renderPass.js.map +1 -1
- package/FrameGraph/frameGraph.d.ts +13 -4
- package/FrameGraph/frameGraph.js +45 -5
- package/FrameGraph/frameGraph.js.map +1 -1
- package/FrameGraph/frameGraphRenderTarget.d.ts +1 -0
- package/FrameGraph/frameGraphRenderTarget.js +3 -0
- package/FrameGraph/frameGraphRenderTarget.js.map +1 -1
- package/FrameGraph/frameGraphTask.d.ts +6 -0
- package/FrameGraph/frameGraphTask.js +15 -0
- package/FrameGraph/frameGraphTask.js.map +1 -1
- package/FrameGraph/frameGraphTypes.d.ts +2 -0
- package/FrameGraph/frameGraphTypes.js.map +1 -1
- package/Materials/Node/nodeMaterial.js +3 -0
- package/Materials/Node/nodeMaterial.js.map +1 -1
- package/Materials/materialHelper.functions.d.ts +29 -7
- package/Materials/materialHelper.functions.js +59 -24
- package/Materials/materialHelper.functions.js.map +1 -1
- package/Materials/shaderMaterial.d.ts +1 -0
- package/Materials/shaderMaterial.js +6 -17
- package/Materials/shaderMaterial.js.map +1 -1
- package/Meshes/mesh.js +1 -1
- package/Meshes/mesh.js.map +1 -1
- package/Misc/screenshotTools.js +2 -8
- package/Misc/screenshotTools.js.map +1 -1
- package/ShadersWGSL/iblVoxelGrid.vertex.d.ts +1 -0
- package/ShadersWGSL/iblVoxelGrid.vertex.js +53 -64
- package/ShadersWGSL/iblVoxelGrid.vertex.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interpolatingBehavior.js","sourceRoot":"","sources":["../../../../../dev/core/src/Behaviors/Cameras/interpolatingBehavior.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Behavior } from \"../behavior\";\r\nimport { CubicEase, EasingFunction } from \"../../Animations/easing\";\r\nimport type { Nullable } from \"../../types\";\r\nimport type { Animatable } from \"../../Animations/animatable.core\";\r\nimport { Animation } from \"../../Animations/animation\";\r\nimport type { Camera } from \"../../Cameras/camera\";\r\nimport type { IColor3Like, IColor4Like, IMatrixLike, IQuaternionLike, IVector2Like, IVector3Like } from \"../../Maths/math.like\";\r\n\r\nexport type AllowedAnimValue = number | IVector2Like | IVector3Like | IQuaternionLike | IMatrixLike | IColor3Like | IColor4Like | SizeLike | undefined;\r\n\r\n/**\r\n * Animate camera property changes with an interpolation effect\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/behaviors/cameraBehaviors\r\n */\r\nexport class InterpolatingBehavior<C extends Camera = Camera> implements Behavior<C> {\r\n /**\r\n * Gets the name of the behavior.\r\n */\r\n public get name(): string {\r\n return \"Interpolating\";\r\n }\r\n\r\n /**\r\n * The easing function to use for interpolation\r\n */\r\n public easingFunction: EasingFunction = new CubicEase();\r\n\r\n /**\r\n * The easing mode (default is EASINGMODE_EASEINOUT)\r\n */\r\n public easingMode = EasingFunction.EASINGMODE_EASEINOUT;\r\n\r\n /**\r\n * Duration of the animation in milliseconds\r\n */\r\n public transitionDuration = 450;\r\n\r\n private _attachedCamera: Nullable<C> = null;\r\n private _animatables: Map<string, Animatable> = new Map<string, Animatable>();\r\n private _promiseResolve?: () => void;\r\n\r\n /**\r\n * Initializes the behavior\r\n */\r\n constructor() {\r\n this.easingFunction.setEasingMode(this.easingMode);\r\n }\r\n\r\n /**\r\n * Initializes the behavior\r\n */\r\n public init(): void {\r\n // Nothing to do on init\r\n }\r\n\r\n /**\r\n * Attaches the behavior to a camera\r\n * @param camera The camera to attach to\r\n */\r\n public attach(camera: C): void {\r\n this._attachedCamera = camera;\r\n }\r\n\r\n /**\r\n * Detaches the behavior from the camera\r\n */\r\n public detach(): void {\r\n if (!this._attachedCamera) {\r\n return;\r\n }\r\n\r\n this.stopAllAnimations();\r\n this._attachedCamera = null;\r\n }\r\n\r\n public get isInterpolating(): boolean {\r\n return this._animatables.size > 0;\r\n }\r\n\r\n /**\r\n * Stops and removes all animations\r\n */\r\n public stopAllAnimations(): void {\r\n if (this._attachedCamera) {\r\n this._animatables.forEach((animatable) => animatable.stop());\r\n }\r\n this._animatables.clear();\r\n this._promiseResolve?.();\r\n this._promiseResolve = undefined;\r\n }\r\n\r\n public updateProperties<K extends keyof C>(properties: Map<K, AllowedAnimValue>): void {\r\n properties.forEach((value, key) => {\r\n if (value !== undefined) {\r\n const animatable = this._animatables.get(String(key));\r\n animatable && (animatable.target = value as unknown as any);\r\n }\r\n });\r\n }\r\n\r\n public async animatePropertiesAsync<K extends keyof C>(\r\n properties: Map<K, AllowedAnimValue>,\r\n transitionDuration: number = this.transitionDuration,\r\n easingFn: EasingFunction = this.easingFunction\r\n ): Promise<void> {\r\n const promise = new Promise<void>((resolve) => {\r\n this._promiseResolve = resolve;\r\n this.stopAllAnimations();\r\n if (!this._attachedCamera) {\r\n this._promiseResolve = undefined;\r\n return resolve();\r\n }\r\n const camera = this._attachedCamera;\r\n const scene = camera.getScene();\r\n\r\n const checkClear = (propertyName: string) => {\r\n // Remove the associated animation from camera once the transition to target is complete so that property animations don't accumulate\r\n for (let i = camera.animations.length - 1; i >= 0; --i) {\r\n if (camera.animations[i].name === propertyName + \"Animation\") {\r\n camera.animations.splice(i, 1);\r\n }\r\n }\r\n\r\n this._animatables.delete(propertyName);\r\n if (this._animatables.size === 0) {\r\n this._promiseResolve = undefined;\r\n resolve();\r\n }\r\n };\r\n\r\n properties.forEach((value, key) => {\r\n if (value !== undefined) {\r\n const propertyName = String(key);\r\n const animation = Animation.CreateAnimation(propertyName, GetAnimationType(value), 60, easingFn);\r\n // Pass false for stopCurrent so that we can interpolate multiple properties at once\r\n const animatable = Animation.TransitionTo(propertyName, value, camera, scene, 60, animation, transitionDuration, () => checkClear(propertyName), false);\r\n if (animatable) {\r\n this._animatables.set(propertyName, animatable);\r\n }\r\n }\r\n });\r\n });\r\n return await promise;\r\n }\r\n}\r\n\r\n// Structural type-guards (no instanceof)\r\nfunction IsQuaternionLike(v: any): v is IQuaternionLike {\r\n return v != null && typeof v.x === \"number\" && typeof v.y === \"number\" && typeof v.z === \"number\" && typeof v.w === \"number\";\r\n}\r\n\r\nfunction IsMatrixLike(v: any): v is IMatrixLike {\r\n return v != null && (Array.isArray((v as any).m) || typeof (v as any).m === \"object\");\r\n}\r\n\r\nfunction IsVector3Like(v: any): v is IVector3Like {\r\n return v != null && typeof v.x === \"number\" && typeof v.y === \"number\" && typeof v.z === \"number\";\r\n}\r\n\r\nfunction IsVector2Like(v: any): v is IVector2Like {\r\n return v != null && typeof v.x === \"number\" && typeof v.y === \"number\";\r\n}\r\n\r\nfunction IsColor3Like(v: any): v is IColor3Like {\r\n return v != null && typeof v.r === \"number\" && typeof v.g === \"number\" && typeof v.b === \"number\";\r\n}\r\n\r\nfunction IsColor4Like(v: any): v is IColor4Like {\r\n return v != null && typeof v.r === \"number\" && typeof v.g === \"number\" && typeof v.b === \"number\" && typeof v.a === \"number\";\r\n}\r\n\r\nexport type SizeLike = { width: number; height: number };\r\n\r\nfunction IsSizeLike(v: any): v is SizeLike {\r\n return v != null && typeof v.width === \"number\" && typeof v.height === \"number\";\r\n}\r\n\r\nconst GetAnimationType = (value: AllowedAnimValue): number => {\r\n if (IsQuaternionLike(value)) {\r\n return Animation.ANIMATIONTYPE_QUATERNION;\r\n }\r\n if (IsMatrixLike(value)) {\r\n return Animation.ANIMATIONTYPE_MATRIX;\r\n }\r\n if (IsVector3Like(value)) {\r\n return Animation.ANIMATIONTYPE_VECTOR3;\r\n }\r\n if (IsVector2Like(value)) {\r\n return Animation.ANIMATIONTYPE_VECTOR2;\r\n }\r\n if (IsColor3Like(value)) {\r\n return Animation.ANIMATIONTYPE_COLOR3;\r\n }\r\n if (IsColor4Like(value)) {\r\n return Animation.ANIMATIONTYPE_COLOR4;\r\n }\r\n if (IsSizeLike(value)) {\r\n return Animation.ANIMATIONTYPE_SIZE;\r\n }\r\n\r\n // Fallback to float for numbers and unknown shapes\r\n return Animation.ANIMATIONTYPE_FLOAT;\r\n};\r\n"]}
|
|
1
|
+
{"version":3,"file":"interpolatingBehavior.js","sourceRoot":"","sources":["../../../../../dev/core/src/Behaviors/Cameras/interpolatingBehavior.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Behavior } from \"../behavior\";\r\nimport { CubicEase, EasingFunction } from \"../../Animations/easing\";\r\nimport type { Nullable } from \"../../types\";\r\nimport type { Animatable } from \"../../Animations/animatable.core\";\r\nimport { Animation } from \"../../Animations/animation\";\r\nimport type { Camera } from \"../../Cameras/camera\";\r\nimport type { IColor3Like, IColor4Like, IMatrixLike, IQuaternionLike, IVector2Like, IVector3Like } from \"../../Maths/math.like\";\r\nimport type { IAnimationKey } from \"../../Animations/animationKey\";\r\n\r\nexport type AllowedAnimValue = number | IVector2Like | IVector3Like | IQuaternionLike | IMatrixLike | IColor3Like | IColor4Like | SizeLike | undefined;\r\n\r\n/**\r\n * Animate camera property changes with an interpolation effect\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/behaviors/cameraBehaviors\r\n */\r\nexport class InterpolatingBehavior<C extends Camera = Camera> implements Behavior<C> {\r\n /**\r\n * Gets the name of the behavior.\r\n */\r\n public get name(): string {\r\n return \"Interpolating\";\r\n }\r\n\r\n /**\r\n * The easing function to use for interpolation\r\n */\r\n public easingFunction: EasingFunction = new CubicEase();\r\n\r\n /**\r\n * The easing mode (default is EASINGMODE_EASEINOUT)\r\n */\r\n public easingMode = EasingFunction.EASINGMODE_EASEINOUT;\r\n\r\n /**\r\n * Duration of the animation in milliseconds\r\n */\r\n public transitionDuration = 450;\r\n\r\n private _attachedCamera: Nullable<C> = null;\r\n private _animatables: Map<string, Animatable> = new Map<string, Animatable>();\r\n private _promiseResolve?: () => void;\r\n\r\n /**\r\n * Initializes the behavior\r\n */\r\n constructor() {\r\n this.easingFunction.setEasingMode(this.easingMode);\r\n }\r\n\r\n /**\r\n * Initializes the behavior\r\n */\r\n public init(): void {\r\n // Nothing to do on init\r\n }\r\n\r\n /**\r\n * Attaches the behavior to a camera\r\n * @param camera The camera to attach to\r\n */\r\n public attach(camera: C): void {\r\n this._attachedCamera = camera;\r\n }\r\n\r\n /**\r\n * Detaches the behavior from the camera\r\n */\r\n public detach(): void {\r\n if (!this._attachedCamera) {\r\n return;\r\n }\r\n\r\n this.stopAllAnimations();\r\n this._attachedCamera = null;\r\n }\r\n\r\n public get isInterpolating(): boolean {\r\n return this._animatables.size > 0;\r\n }\r\n\r\n /**\r\n * Stops and removes all animations\r\n */\r\n public stopAllAnimations(): void {\r\n if (this._attachedCamera) {\r\n this._animatables.forEach((animatable) => animatable.stop());\r\n }\r\n this._animatables.clear();\r\n this._promiseResolve?.();\r\n this._promiseResolve = undefined;\r\n }\r\n\r\n public updateProperties<K extends keyof C>(properties: Map<K, AllowedAnimValue>): void {\r\n properties.forEach((value, key) => {\r\n if (value !== undefined) {\r\n const animatable = this._animatables.get(String(key));\r\n animatable && (animatable.target = value as unknown as any);\r\n }\r\n });\r\n }\r\n\r\n public async animatePropertiesAsync<K extends keyof C>(\r\n properties: Map<K, AllowedAnimValue>,\r\n transitionDuration: number = this.transitionDuration,\r\n easingFn: EasingFunction = this.easingFunction,\r\n customKeys?: Map<K, IAnimationKey[]>\r\n ): Promise<void> {\r\n const promise = new Promise<void>((resolve) => {\r\n this._promiseResolve = resolve;\r\n this.stopAllAnimations();\r\n if (!this._attachedCamera) {\r\n this._promiseResolve = undefined;\r\n return resolve();\r\n }\r\n const camera = this._attachedCamera;\r\n const scene = camera.getScene();\r\n\r\n const checkClear = (propertyName: string) => {\r\n // Remove the associated animation from camera once the transition to target is complete so that property animations don't accumulate\r\n for (let i = camera.animations.length - 1; i >= 0; --i) {\r\n if (camera.animations[i].name === propertyName + \"Animation\") {\r\n camera.animations.splice(i, 1);\r\n }\r\n }\r\n\r\n this._animatables.delete(propertyName);\r\n if (this._animatables.size === 0) {\r\n this._promiseResolve = undefined;\r\n resolve();\r\n }\r\n };\r\n\r\n properties.forEach((value, key) => {\r\n if (value !== undefined) {\r\n const propertyName = String(key);\r\n const animation = Animation.CreateAnimation(propertyName, GetAnimationType(value), 60, easingFn);\r\n // Pass false for stopCurrent so that we can interpolate multiple properties at once\r\n const animatable = Animation.TransitionTo(\r\n propertyName,\r\n value,\r\n camera,\r\n scene,\r\n 60,\r\n animation,\r\n transitionDuration,\r\n () => checkClear(propertyName),\r\n false,\r\n customKeys?.get(key)\r\n );\r\n if (animatable) {\r\n this._animatables.set(propertyName, animatable);\r\n }\r\n }\r\n });\r\n });\r\n return await promise;\r\n }\r\n}\r\n\r\n// Structural type-guards (no instanceof)\r\nfunction IsQuaternionLike(v: any): v is IQuaternionLike {\r\n return v != null && typeof v.x === \"number\" && typeof v.y === \"number\" && typeof v.z === \"number\" && typeof v.w === \"number\";\r\n}\r\n\r\nfunction IsMatrixLike(v: any): v is IMatrixLike {\r\n return v != null && (Array.isArray((v as any).m) || typeof (v as any).m === \"object\");\r\n}\r\n\r\nfunction IsVector3Like(v: any): v is IVector3Like {\r\n return v != null && typeof v.x === \"number\" && typeof v.y === \"number\" && typeof v.z === \"number\";\r\n}\r\n\r\nfunction IsVector2Like(v: any): v is IVector2Like {\r\n return v != null && typeof v.x === \"number\" && typeof v.y === \"number\";\r\n}\r\n\r\nfunction IsColor3Like(v: any): v is IColor3Like {\r\n return v != null && typeof v.r === \"number\" && typeof v.g === \"number\" && typeof v.b === \"number\";\r\n}\r\n\r\nfunction IsColor4Like(v: any): v is IColor4Like {\r\n return v != null && typeof v.r === \"number\" && typeof v.g === \"number\" && typeof v.b === \"number\" && typeof v.a === \"number\";\r\n}\r\n\r\nexport type SizeLike = { width: number; height: number };\r\n\r\nfunction IsSizeLike(v: any): v is SizeLike {\r\n return v != null && typeof v.width === \"number\" && typeof v.height === \"number\";\r\n}\r\n\r\nconst GetAnimationType = (value: AllowedAnimValue): number => {\r\n if (IsQuaternionLike(value)) {\r\n return Animation.ANIMATIONTYPE_QUATERNION;\r\n }\r\n if (IsMatrixLike(value)) {\r\n return Animation.ANIMATIONTYPE_MATRIX;\r\n }\r\n if (IsVector3Like(value)) {\r\n return Animation.ANIMATIONTYPE_VECTOR3;\r\n }\r\n if (IsVector2Like(value)) {\r\n return Animation.ANIMATIONTYPE_VECTOR2;\r\n }\r\n if (IsColor3Like(value)) {\r\n return Animation.ANIMATIONTYPE_COLOR3;\r\n }\r\n if (IsColor4Like(value)) {\r\n return Animation.ANIMATIONTYPE_COLOR4;\r\n }\r\n if (IsSizeLike(value)) {\r\n return Animation.ANIMATIONTYPE_SIZE;\r\n }\r\n\r\n // Fallback to float for numbers and unknown shapes\r\n return Animation.ANIMATIONTYPE_FLOAT;\r\n};\r\n"]}
|
|
@@ -88,6 +88,7 @@ export declare class GeospatialCamera extends Camera {
|
|
|
88
88
|
* @param targetCenter
|
|
89
89
|
*/
|
|
90
90
|
updateFlyToDestination(targetYaw?: number, targetPitch?: number, targetRadius?: number, targetCenter?: Vector3): void;
|
|
91
|
+
private _customKeys;
|
|
91
92
|
/**
|
|
92
93
|
* Animate camera towards passed in property values. If undefined, will use current value
|
|
93
94
|
* @param targetYaw
|
|
@@ -96,17 +97,19 @@ export declare class GeospatialCamera extends Camera {
|
|
|
96
97
|
* @param targetCenter
|
|
97
98
|
* @param flightDurationMs
|
|
98
99
|
* @param easingFunction
|
|
100
|
+
* @param overshootRadiusScale If defined, will first fly to radius*scale before flying to targetRadius to create a "bounce" effect
|
|
99
101
|
* @returns Promise that will return when the animation is complete (or interuppted by pointer input)
|
|
100
102
|
*/
|
|
101
|
-
flyToAsync(targetYaw?: number, targetPitch?: number, targetRadius?: number, targetCenter?: Vector3, flightDurationMs?: number, easingFunction?: EasingFunction): Promise<void>;
|
|
103
|
+
flyToAsync(targetYaw?: number, targetPitch?: number, targetRadius?: number, targetCenter?: Vector3, flightDurationMs?: number, easingFunction?: EasingFunction, overshootRadiusScale?: number): Promise<void>;
|
|
102
104
|
/**
|
|
103
105
|
* Helper function to move camera towards a given point by radiusScale% of radius (by default 50%)
|
|
104
106
|
* @param destination point to move towards
|
|
105
107
|
* @param radiusScale value between 0 and 1, % of radius to move
|
|
106
108
|
* @param durationMs duration of flight, default 1s
|
|
107
109
|
* @param easingFn optional easing function for flight interpolation of properties
|
|
110
|
+
* @param overshootRadiusScale optional scale to apply to the current radius to achieve a 'hop' animation
|
|
108
111
|
*/
|
|
109
|
-
flyToPointAsync(destination: Vector3, radiusScale?: number, durationMs?: number, easingFn?: EasingFunction): Promise<void>;
|
|
112
|
+
flyToPointAsync(destination: Vector3, radiusScale?: number, durationMs?: number, easingFn?: EasingFunction, overshootRadiusScale?: number): Promise<void>;
|
|
110
113
|
private _limits;
|
|
111
114
|
get limits(): GeospatialLimits;
|
|
112
115
|
private _resetToDefault;
|
|
@@ -119,9 +122,15 @@ export declare class GeospatialCamera extends Camera {
|
|
|
119
122
|
* This rotation keeps the camera oriented towards the globe as it orbits around it. This is different from cameraCentricRotation which is when the camera rotates around its own axis
|
|
120
123
|
*/
|
|
121
124
|
private _applyGeocentricRotation;
|
|
122
|
-
private
|
|
125
|
+
private _getCenterAndRadiusFromZoomToPoint;
|
|
126
|
+
/**
|
|
127
|
+
* Apply zoom by moving the camera toward/away from a target point.
|
|
128
|
+
*/
|
|
123
129
|
private _applyZoom;
|
|
130
|
+
private _zoomToPoint;
|
|
131
|
+
private _zoomAlongLookAt;
|
|
124
132
|
_checkInputs(): void;
|
|
133
|
+
private _recalculateCenter;
|
|
125
134
|
attachControl(noPreventDefault?: boolean): void;
|
|
126
135
|
detachControl(): void;
|
|
127
136
|
}
|
|
@@ -4,7 +4,7 @@ import { Epsilon } from "../Maths/math.constants.js";
|
|
|
4
4
|
import { Camera } from "./camera.js";
|
|
5
5
|
import { GeospatialLimits } from "./Limits/geospatialLimits.js";
|
|
6
6
|
import { ClampCenterFromPolesInPlace, ComputeLocalBasisToRefs, GeospatialCameraMovement } from "./geospatialCameraMovement.js";
|
|
7
|
-
import { Vector3CopyToRef
|
|
7
|
+
import { Vector3CopyToRef } from "../Maths/math.vector.functions.js";
|
|
8
8
|
import { Clamp } from "../Maths/math.scalar.functions.js";
|
|
9
9
|
import { InterpolatingBehavior } from "../Behaviors/Cameras/interpolatingBehavior.js";
|
|
10
10
|
/**
|
|
@@ -30,11 +30,12 @@ export class GeospatialCamera extends Camera {
|
|
|
30
30
|
this._tempEast = new Vector3();
|
|
31
31
|
this._tempNorth = new Vector3();
|
|
32
32
|
this._tempUp = new Vector3();
|
|
33
|
+
this._customKeys = new Map();
|
|
33
34
|
this._limits = new GeospatialLimits(options.planetRadius);
|
|
34
35
|
this._resetToDefault(this._limits);
|
|
35
36
|
this._flyingBehavior = new InterpolatingBehavior();
|
|
36
37
|
this.addBehavior(this._flyingBehavior);
|
|
37
|
-
this.movement = new GeospatialCameraMovement(scene, this._limits, this.position, this.center, this._lookAtVector, pickPredicate);
|
|
38
|
+
this.movement = new GeospatialCameraMovement(scene, this._limits, this.position, this.center, this._lookAtVector, pickPredicate, this._flyingBehavior);
|
|
38
39
|
this.pickPredicate = pickPredicate;
|
|
39
40
|
this.inputs = new GeospatialCameraInputsManager(this);
|
|
40
41
|
this.inputs.addMouse().addMouseWheel().addKeyboard();
|
|
@@ -162,15 +163,29 @@ export class GeospatialCamera extends Camera {
|
|
|
162
163
|
* @param targetCenter
|
|
163
164
|
* @param flightDurationMs
|
|
164
165
|
* @param easingFunction
|
|
166
|
+
* @param overshootRadiusScale If defined, will first fly to radius*scale before flying to targetRadius to create a "bounce" effect
|
|
165
167
|
* @returns Promise that will return when the animation is complete (or interuppted by pointer input)
|
|
166
168
|
*/
|
|
167
|
-
async flyToAsync(targetYaw, targetPitch, targetRadius, targetCenter, flightDurationMs = 1000, easingFunction) {
|
|
169
|
+
async flyToAsync(targetYaw, targetPitch, targetRadius, targetCenter, flightDurationMs = 1000, easingFunction, overshootRadiusScale) {
|
|
168
170
|
this._flyToTargets.clear();
|
|
171
|
+
this._customKeys.clear();
|
|
169
172
|
this._flyToTargets.set("yaw", targetYaw);
|
|
170
173
|
this._flyToTargets.set("pitch", targetPitch);
|
|
171
174
|
this._flyToTargets.set("radius", targetRadius);
|
|
172
175
|
this._flyToTargets.set("center", targetCenter);
|
|
173
|
-
|
|
176
|
+
const overshootRadius = overshootRadiusScale !== undefined ? this.radius * overshootRadiusScale : undefined;
|
|
177
|
+
if (overshootRadius !== undefined && overshootRadius !== targetRadius) {
|
|
178
|
+
// Start the animation with overshoot radius
|
|
179
|
+
const frameRate = 60;
|
|
180
|
+
const totalFrames = (flightDurationMs / 1000) * frameRate;
|
|
181
|
+
const midFrame = totalFrames / 2;
|
|
182
|
+
this._customKeys.set("radius", [
|
|
183
|
+
{ frame: 0, value: this.radius },
|
|
184
|
+
{ frame: midFrame, value: overshootRadius },
|
|
185
|
+
{ frame: totalFrames, value: targetRadius },
|
|
186
|
+
]);
|
|
187
|
+
}
|
|
188
|
+
return await this._flyingBehavior.animatePropertiesAsync(this._flyToTargets, flightDurationMs, easingFunction, this._customKeys);
|
|
174
189
|
}
|
|
175
190
|
/**
|
|
176
191
|
* Helper function to move camera towards a given point by radiusScale% of radius (by default 50%)
|
|
@@ -178,12 +193,13 @@ export class GeospatialCamera extends Camera {
|
|
|
178
193
|
* @param radiusScale value between 0 and 1, % of radius to move
|
|
179
194
|
* @param durationMs duration of flight, default 1s
|
|
180
195
|
* @param easingFn optional easing function for flight interpolation of properties
|
|
196
|
+
* @param overshootRadiusScale optional scale to apply to the current radius to achieve a 'hop' animation
|
|
181
197
|
*/
|
|
182
|
-
async flyToPointAsync(destination, radiusScale = 0.5, durationMs = 1000, easingFn) {
|
|
183
|
-
const direction = destination.subtractToRef(this.position, this._tempPosition).normalize();
|
|
198
|
+
async flyToPointAsync(destination, radiusScale = 0.5, durationMs = 1000, easingFn, overshootRadiusScale) {
|
|
184
199
|
// Zoom to radiusScale% of radius towards the given destination point
|
|
185
|
-
const
|
|
186
|
-
|
|
200
|
+
const zoomDistance = this.radius * radiusScale;
|
|
201
|
+
const newRadius = this._getCenterAndRadiusFromZoomToPoint(destination, zoomDistance, this._tempCenter);
|
|
202
|
+
await this.flyToAsync(undefined, undefined, newRadius, this._tempCenter, durationMs, easingFn, overshootRadiusScale);
|
|
187
203
|
}
|
|
188
204
|
get limits() {
|
|
189
205
|
return this._limits;
|
|
@@ -251,54 +267,93 @@ export class GeospatialCamera extends Camera {
|
|
|
251
267
|
this._setOrientation(yaw, pitch, this._radius, this._geocentricRotationPt);
|
|
252
268
|
}
|
|
253
269
|
}
|
|
254
|
-
|
|
255
|
-
//
|
|
256
|
-
|
|
257
|
-
// Project zoom vector onto lookAt vector to find the amount the camera-to-center distance should change.
|
|
258
|
-
// - zoom vector is normalized
|
|
259
|
-
// - distance is how much to move in this call
|
|
260
|
-
const directionDotLookAt = Vector3Dot(zoomVector, this._lookAtVector);
|
|
261
|
-
const hasRadialComponent = Math.abs(directionDotLookAt) > Epsilon;
|
|
262
|
-
const requestedRadius = hasRadialComponent ? this._radius - distance * directionDotLookAt : this._radius;
|
|
270
|
+
_getCenterAndRadiusFromZoomToPoint(targetPoint, distance, newCenter) {
|
|
271
|
+
// Clamp new radius to limits
|
|
272
|
+
const requestedRadius = this._radius - distance;
|
|
263
273
|
const newRadius = Clamp(requestedRadius, this.limits.radiusMin, this.limits.radiusMax);
|
|
264
|
-
const
|
|
265
|
-
const
|
|
266
|
-
//
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
//
|
|
274
|
+
const actualDistance = this._radius - newRadius;
|
|
275
|
+
const actualRatio = actualDistance / this._radius;
|
|
276
|
+
// Direction from current center to target point
|
|
277
|
+
const directionToTarget = TmpVectors.Vector3[0];
|
|
278
|
+
targetPoint.subtractToRef(this._center, directionToTarget);
|
|
279
|
+
// Move center toward target by the ratio amount
|
|
280
|
+
const centerOffset = TmpVectors.Vector3[1];
|
|
281
|
+
directionToTarget.scaleToRef(actualRatio, centerOffset);
|
|
282
|
+
// Calculate new center
|
|
283
|
+
this._center.addToRef(centerOffset, newCenter);
|
|
284
|
+
// Preserve center altitude (distance from planet origin)
|
|
270
285
|
const currentCenterRadius = this._center.length();
|
|
271
286
|
const newCenterRadius = newCenter.length();
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
Vector3CopyToRef(newCenter, centerRef);
|
|
276
|
-
// Return new radius
|
|
287
|
+
if (newCenterRadius > Epsilon) {
|
|
288
|
+
newCenter.scaleInPlace(currentCenterRadius / newCenterRadius);
|
|
289
|
+
}
|
|
277
290
|
return newRadius;
|
|
278
291
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
292
|
+
/**
|
|
293
|
+
* Apply zoom by moving the camera toward/away from a target point.
|
|
294
|
+
*/
|
|
295
|
+
_applyZoom() {
|
|
296
|
+
const zoomDelta = this.movement.zoomDeltaCurrentFrame;
|
|
297
|
+
const pickedPoint = this.movement.computedPerFrameZoomPickPoint;
|
|
298
|
+
if (pickedPoint) {
|
|
299
|
+
// Zoom toward the picked point under cursor
|
|
300
|
+
this._zoomToPoint(pickedPoint, zoomDelta);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
// Zoom along lookAt vector (fallback when no surface under cursor)
|
|
304
|
+
this._zoomAlongLookAt(zoomDelta);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
_zoomToPoint(targetPoint, distance) {
|
|
308
|
+
const newRadius = this._getCenterAndRadiusFromZoomToPoint(targetPoint, distance, this._tempCenter);
|
|
309
|
+
// Apply the new orientation
|
|
310
|
+
this._setOrientation(this._yaw, this._pitch, newRadius, this._tempCenter);
|
|
311
|
+
}
|
|
312
|
+
_zoomAlongLookAt(distance) {
|
|
313
|
+
// Clamp radius to limits
|
|
314
|
+
const requestedRadius = this._radius - distance;
|
|
315
|
+
const newRadius = Clamp(requestedRadius, this.limits.radiusMin, this.limits.radiusMax);
|
|
316
|
+
// Simply change radius without moving center
|
|
317
|
+
this._setOrientation(this._yaw, this._pitch, newRadius, this._center);
|
|
283
318
|
}
|
|
284
319
|
_checkInputs() {
|
|
285
320
|
this.inputs.checkInputs();
|
|
286
321
|
// Let movement class handle all per-frame logic
|
|
287
322
|
this.movement.computeCurrentFrameDeltas();
|
|
323
|
+
let recalculateCenter = false;
|
|
288
324
|
if (this.movement.panDeltaCurrentFrame.lengthSquared() > 0) {
|
|
289
325
|
this._applyGeocentricTranslation();
|
|
290
|
-
|
|
326
|
+
recalculateCenter = true;
|
|
291
327
|
}
|
|
292
328
|
if (this.movement.rotationDeltaCurrentFrame.lengthSquared() > 0) {
|
|
293
329
|
this._applyGeocentricRotation();
|
|
294
|
-
this._isViewMatrixDirty = true;
|
|
295
330
|
}
|
|
296
331
|
if (Math.abs(this.movement.zoomDeltaCurrentFrame) > Epsilon) {
|
|
297
|
-
this._applyZoom(
|
|
298
|
-
|
|
332
|
+
this._applyZoom();
|
|
333
|
+
recalculateCenter = true;
|
|
299
334
|
}
|
|
335
|
+
// After a movement impacting center or radius, recalculate the center point to ensure it's still on the surface.
|
|
336
|
+
recalculateCenter && this._recalculateCenter();
|
|
300
337
|
super._checkInputs();
|
|
301
338
|
}
|
|
339
|
+
_recalculateCenter() {
|
|
340
|
+
// Wait until dragging is complete to avoid wasted raycasting
|
|
341
|
+
if (!this.movement.isDragging) {
|
|
342
|
+
const newCenter = this.movement.pickAlongVector(this._lookAtVector);
|
|
343
|
+
if (newCenter?.pickedPoint) {
|
|
344
|
+
// Direction from new center to origin
|
|
345
|
+
const centerToOrigin = TmpVectors.Vector3[4];
|
|
346
|
+
centerToOrigin.copyFrom(newCenter.pickedPoint).negateInPlace().normalize();
|
|
347
|
+
// Check if this direction aligns with camera's lookAt vector
|
|
348
|
+
const dotProduct = Vector3.Dot(this._lookAtVector, centerToOrigin);
|
|
349
|
+
// Only update if the center is looking toward the origin (dot product > 0) to avoid a center on the opposite side of globe
|
|
350
|
+
if (dotProduct > 0) {
|
|
351
|
+
const newRadius = Vector3.Distance(this.position, newCenter.pickedPoint);
|
|
352
|
+
this._setOrientation(this._yaw, this._pitch, newRadius, newCenter.pickedPoint);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
302
357
|
attachControl(noPreventDefault) {
|
|
303
358
|
this.inputs.attachElement(noPreventDefault);
|
|
304
359
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geospatialCamera.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/geospatialCamera.ts"],"names":[],"mappings":"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","sourcesContent":["import { GeospatialCameraInputsManager } from \"./geospatialCameraInputsManager\";\r\nimport { Vector3, Matrix, TmpVectors } from \"../Maths/math.vector\";\r\nimport { Epsilon } from \"../Maths/math.constants\";\r\nimport { Camera } from \"./camera\";\r\nimport type { Scene } from \"../scene\";\r\nimport type { MeshPredicate } from \"../Culling/ray.core\";\r\nimport type { DeepImmutable } from \"../types\";\r\nimport { GeospatialLimits } from \"./Limits/geospatialLimits\";\r\nimport { ClampCenterFromPolesInPlace, ComputeLocalBasisToRefs, GeospatialCameraMovement } from \"./geospatialCameraMovement\";\r\nimport type { IVector3Like } from \"../Maths/math.like\";\r\nimport { Vector3CopyToRef, Vector3Dot } from \"../Maths/math.vector.functions\";\r\nimport { Clamp } from \"../Maths/math.scalar.functions\";\r\nimport type { AllowedAnimValue } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\nimport { InterpolatingBehavior } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\nimport type { EasingFunction } from \"../Animations/easing\";\r\n\r\ntype CameraOptions = {\r\n planetRadius: number; // Radius of the planet\r\n};\r\n\r\n/**\r\n * @experimental\r\n * This camera's movements are limited to a camera orbiting a globe, and as the API evolves it will introduce conversions between cartesian coordinates and true lat/long/alt\r\n *\r\n * Please note this is marked as experimental and the API (including the constructor!) will change until we remove that flag\r\n */\r\nexport class GeospatialCamera extends Camera {\r\n override inputs: GeospatialCameraInputsManager;\r\n\r\n /** If supplied, will be used when picking the globe */\r\n public pickPredicate?: MeshPredicate;\r\n\r\n /** Movement controller that turns input pixelDeltas into currentFrameDeltas used by camera*/\r\n public readonly movement: GeospatialCameraMovement;\r\n\r\n // Temp vars\r\n private _tempPosition: Vector3 = new Vector3();\r\n private _tempCenter = new Vector3();\r\n\r\n private _viewMatrix = new Matrix();\r\n private _isViewMatrixDirty: boolean;\r\n private _lookAtVector: Vector3 = new Vector3();\r\n\r\n /** Behavior used for smooth flying animations */\r\n private _flyingBehavior: InterpolatingBehavior<GeospatialCamera>;\r\n private _flyToTargets: Map<keyof GeospatialCamera, AllowedAnimValue> = new Map();\r\n\r\n constructor(name: string, scene: Scene, options: CameraOptions, pickPredicate?: MeshPredicate) {\r\n super(name, new Vector3(), scene);\r\n\r\n this._limits = new GeospatialLimits(options.planetRadius);\r\n this._resetToDefault(this._limits);\r\n\r\n this._flyingBehavior = new InterpolatingBehavior();\r\n this.addBehavior(this._flyingBehavior);\r\n\r\n this.movement = new GeospatialCameraMovement(scene, this._limits, this.position, this.center, this._lookAtVector, pickPredicate);\r\n\r\n this.pickPredicate = pickPredicate;\r\n this.inputs = new GeospatialCameraInputsManager(this);\r\n this.inputs.addMouse().addMouseWheel().addKeyboard();\r\n }\r\n\r\n private _center: Vector3 = new Vector3();\r\n /** The point on the globe that we are anchoring around. If no alternate rotation point is supplied, this will represent the center of screen*/\r\n public get center(): Vector3 {\r\n return this._center;\r\n }\r\n\r\n /**\r\n * Sets the camera position to orbit around a new center point\r\n * @param center The world position (ECEF) to orbit around\r\n */\r\n public set center(center: IVector3Like) {\r\n this._center.copyFromFloats(center.x, center.y, center.z);\r\n this._setOrientation(this._yaw, this._pitch, this._radius, this._center);\r\n }\r\n\r\n private _yaw: number = 0;\r\n /**\r\n * Gets the camera's yaw (rotation around the geocentric normal) in radians\r\n */\r\n public get yaw(): number {\r\n return this._yaw;\r\n }\r\n\r\n /**\r\n * Sets the camera's yaw (rotation around the geocentric normal)\r\n * @param yaw The desired yaw angle in radians (0 = north, π/2 = east)\r\n */\r\n public set yaw(yaw: number) {\r\n this._setOrientation(yaw, this.pitch, this.radius, this.center);\r\n }\r\n\r\n private _pitch: number = 0;\r\n\r\n /**\r\n * Gets the camera's pitch (angle from looking straight at globe)\r\n * Pitch is measured from looking straight down at planet center:\r\n * - zero pitch = looking straight at planet center (down)\r\n * - positive pitch = tilting up away from planet\r\n * - π/2 pitch = looking at horizon (perpendicular to geocentric normal)\r\n */\r\n public get pitch(): number {\r\n return this._pitch;\r\n }\r\n\r\n /**\r\n * Sets the camera's pitch (angle from looking straight at globe)\r\n * @param pitch The desired pitch angle in radians (0 = looking at planet center, π/2 = looking at horizon)\r\n */\r\n public set pitch(pitch: number) {\r\n this._setOrientation(this.yaw, pitch, this.radius, this.center);\r\n }\r\n\r\n private _radius: number = 0;\r\n public get radius(): number {\r\n return this._radius;\r\n }\r\n\r\n /**\r\n * Sets the camera's distance from the current center point\r\n * @param radius The desired radius\r\n */\r\n public set radius(radius: number) {\r\n this._setOrientation(this.yaw, this.pitch, radius, this.center);\r\n }\r\n\r\n protected _checkLimits() {\r\n const limits = this.limits;\r\n this._yaw = Clamp(this._yaw, limits.yawMin, limits.yawMax);\r\n this._pitch = Clamp(this._pitch, limits.pitchMin, limits.pitchMax);\r\n this._radius = Clamp(this._radius, limits.radiusMin, limits.radiusMax);\r\n this._center = ClampCenterFromPolesInPlace(this._center);\r\n }\r\n\r\n private _tempVect = new Vector3();\r\n private _tempEast = new Vector3();\r\n private _tempNorth = new Vector3();\r\n private _tempUp = new Vector3();\r\n\r\n private _setOrientation(yaw: number, pitch: number, radius: number, center: DeepImmutable<IVector3Like>): void {\r\n this._yaw = yaw;\r\n this._pitch = pitch;\r\n this._radius = radius;\r\n\r\n Vector3CopyToRef(center, this._center);\r\n\r\n // Clamp to limits\r\n this._checkLimits();\r\n\r\n // Refresh local basis at center (treat these as read-only for the whole call)\r\n ComputeLocalBasisToRefs(this._center, this._tempEast, this._tempNorth, this._tempUp);\r\n\r\n // Trig\r\n const yawScale = this._scene.useRightHandedSystem ? 1 : -1;\r\n const cosYaw = Math.cos(this._yaw * yawScale);\r\n const sinYaw = Math.sin(this._yaw * yawScale);\r\n const sinPitch = Math.sin(this._pitch); // horizontal weight\r\n const cosPitch = Math.cos(this._pitch); // vertical weight (toward center)\r\n\r\n // Temps\r\n const horiz = TmpVectors.Vector3[0];\r\n const t1 = TmpVectors.Vector3[1];\r\n const t2 = TmpVectors.Vector3[2];\r\n const right = TmpVectors.Vector3[3];\r\n\r\n // horizontalDirection = North*cosYaw + East*sinYaw (avoids mutating _temp basis vectors)\r\n horiz.copyFrom(this._tempNorth).scaleInPlace(cosYaw).addInPlace(t1.copyFrom(this._tempEast).scaleInPlace(sinYaw));\r\n\r\n // look = horiz*sinPitch - Up*cosPitch\r\n this._lookAtVector.copyFrom(horiz).scaleInPlace(sinPitch).addInPlace(t2.copyFrom(this._tempUp).scaleInPlace(-cosPitch)).normalize(); // keep it unit\r\n\r\n // Build an orthonormal up aligned with geocentric Up\r\n // right = normalize(cross(upRef, look))\r\n Vector3.CrossToRef(this._tempUp, this._lookAtVector, right);\r\n\r\n // up = normalize(cross(look, right))\r\n Vector3.CrossToRef(this._lookAtVector, right, this.upVector);\r\n\r\n // Position = center - look * radius (preserve unit look)\r\n this._tempVect.copyFrom(this._lookAtVector).scaleInPlace(-this._radius);\r\n this._tempPosition.copyFrom(this._center).addInPlace(this._tempVect);\r\n\r\n this._position.copyFrom(this._tempPosition);\r\n\r\n this._isViewMatrixDirty = true;\r\n }\r\n\r\n /** The point around which the camera will geocentrically rotate. Uses center (pt we are anchored to) if no alternateRotationPt is defined */\r\n private get _geocentricRotationPt(): Vector3 {\r\n return this.movement.alternateRotationPt ?? this.center;\r\n }\r\n\r\n /**\r\n * If camera is actively in flight, will update the target properties and use up the remaining duration from original flyTo call\r\n *\r\n * To start a new flyTo curve entirely, call into flyToAsync again (it will stop the inflight animation)\r\n * @param targetYaw\r\n * @param targetPitch\r\n * @param targetRadius\r\n * @param targetCenter\r\n */\r\n public updateFlyToDestination(targetYaw?: number, targetPitch?: number, targetRadius?: number, targetCenter?: Vector3): void {\r\n this._flyToTargets.clear();\r\n\r\n this._flyToTargets.set(\"yaw\", targetYaw);\r\n this._flyToTargets.set(\"pitch\", targetPitch);\r\n this._flyToTargets.set(\"radius\", targetRadius);\r\n this._flyToTargets.set(\"center\", targetCenter);\r\n\r\n this._flyingBehavior.updateProperties(this._flyToTargets);\r\n }\r\n\r\n /**\r\n * Animate camera towards passed in property values. If undefined, will use current value\r\n * @param targetYaw\r\n * @param targetPitch\r\n * @param targetRadius\r\n * @param targetCenter\r\n * @param flightDurationMs\r\n * @param easingFunction\r\n * @returns Promise that will return when the animation is complete (or interuppted by pointer input)\r\n */\r\n public async flyToAsync(\r\n targetYaw?: number,\r\n targetPitch?: number,\r\n targetRadius?: number,\r\n targetCenter?: Vector3,\r\n flightDurationMs: number = 1000,\r\n easingFunction?: EasingFunction\r\n ): Promise<void> {\r\n this._flyToTargets.clear();\r\n\r\n this._flyToTargets.set(\"yaw\", targetYaw);\r\n this._flyToTargets.set(\"pitch\", targetPitch);\r\n this._flyToTargets.set(\"radius\", targetRadius);\r\n this._flyToTargets.set(\"center\", targetCenter);\r\n\r\n return await this._flyingBehavior.animatePropertiesAsync(this._flyToTargets, flightDurationMs, easingFunction);\r\n }\r\n\r\n /**\r\n * Helper function to move camera towards a given point by radiusScale% of radius (by default 50%)\r\n * @param destination point to move towards\r\n * @param radiusScale value between 0 and 1, % of radius to move\r\n * @param durationMs duration of flight, default 1s\r\n * @param easingFn optional easing function for flight interpolation of properties\r\n */\r\n public async flyToPointAsync(destination: Vector3, radiusScale: number = 0.5, durationMs: number = 1000, easingFn?: EasingFunction) {\r\n const direction = destination.subtractToRef(this.position, this._tempPosition).normalize();\r\n // Zoom to radiusScale% of radius towards the given destination point\r\n const newRadius = this._getRadiusAndCenterFromZoomTowards(direction, this.radius * radiusScale, this._tempCenter);\r\n await this.flyToAsync(undefined, undefined, newRadius, this._tempCenter, durationMs, easingFn);\r\n }\r\n\r\n private _limits: GeospatialLimits;\r\n public get limits(): GeospatialLimits {\r\n return this._limits;\r\n }\r\n\r\n private _resetToDefault(limits: GeospatialLimits): void {\r\n // Camera configuration vars\r\n const maxCameraRadius = limits.altitudeMax !== undefined ? limits.planetRadius + limits.altitudeMax : undefined;\r\n const restingAltitude = maxCameraRadius ?? limits.planetRadius * 4;\r\n this.position.copyFromFloats(restingAltitude, 0, 0);\r\n this._center.copyFromFloats(limits.planetRadius, 0, 0);\r\n this._radius = Vector3.Distance(this.position, this.center);\r\n\r\n // Temp vars\r\n this._tempPosition = new Vector3();\r\n\r\n // View matrix calculation vars\r\n this._viewMatrix = Matrix.Identity();\r\n this._center.subtractToRef(this._position, this._lookAtVector).normalize(); // Lookat vector of the camera\r\n this.upVector = Vector3.Up(); // Up vector of the camera (does work for -X look at)\r\n this._isViewMatrixDirty = true;\r\n\r\n this._setOrientation(this._yaw, this._pitch, this._radius, this._center);\r\n }\r\n\r\n /** @internal */\r\n override _getViewMatrix() {\r\n if (!this._isViewMatrixDirty) {\r\n return this._viewMatrix;\r\n }\r\n this._isViewMatrixDirty = false;\r\n\r\n // Ensure vectors are normalized\r\n this.upVector.normalize();\r\n this._lookAtVector.normalize();\r\n\r\n // Calculate view matrix with camera position and center\r\n if (this.getScene().useRightHandedSystem) {\r\n Matrix.LookAtRHToRef(this.position, this._center, this.upVector, this._viewMatrix);\r\n } else {\r\n Matrix.LookAtLHToRef(this.position, this._center, this.upVector, this._viewMatrix);\r\n }\r\n\r\n return this._viewMatrix;\r\n }\r\n\r\n /** @internal */\r\n override _isSynchronizedViewMatrix(): boolean {\r\n if (!super._isSynchronizedViewMatrix() || this._isViewMatrixDirty) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n private _applyGeocentricTranslation() {\r\n // Store pending position (without any corrections applied)\r\n this.center.addToRef(this.movement.panDeltaCurrentFrame, this._tempPosition);\r\n\r\n if (!this.movement.isInterpolating) {\r\n // Calculate the position correction to keep camera at the same radius when applying translation\r\n this._tempPosition.normalize().scaleInPlace(this.center.length());\r\n }\r\n // Set center which will call _setOrientation\r\n this.center = this._tempPosition;\r\n }\r\n\r\n /**\r\n * This rotation keeps the camera oriented towards the globe as it orbits around it. This is different from cameraCentricRotation which is when the camera rotates around its own axis\r\n */\r\n private _applyGeocentricRotation(): void {\r\n const rotationDeltaCurrentFrame = this.movement.rotationDeltaCurrentFrame;\r\n if (rotationDeltaCurrentFrame.x !== 0 || rotationDeltaCurrentFrame.y !== 0) {\r\n const pitch = rotationDeltaCurrentFrame.x !== 0 ? Clamp(this._pitch + rotationDeltaCurrentFrame.x, 0, 0.5 * Math.PI - Epsilon) : this._pitch;\r\n const yaw = rotationDeltaCurrentFrame.y !== 0 ? this._yaw + rotationDeltaCurrentFrame.y : this._yaw;\r\n\r\n // TODO: If _geocentricRotationPt is not the center, this will need to be adjusted.\r\n this._setOrientation(yaw, pitch, this._radius, this._geocentricRotationPt);\r\n }\r\n }\r\n\r\n private _getRadiusAndCenterFromZoomTowards(zoomVector: Vector3, distance: number, centerRef: Vector3): number {\r\n // TODO this function will be re-worked shortly after checkin, becuase today it breaks down if you zoom to a point past the center\r\n // (ex: tilted view zooming towards cursor near horizon where the center is closer than the cursor point).\r\n\r\n // Project zoom vector onto lookAt vector to find the amount the camera-to-center distance should change.\r\n // - zoom vector is normalized\r\n // - distance is how much to move in this call\r\n const directionDotLookAt = Vector3Dot(zoomVector, this._lookAtVector);\r\n const hasRadialComponent = Math.abs(directionDotLookAt) > Epsilon;\r\n const requestedRadius = hasRadialComponent ? this._radius - distance * directionDotLookAt : this._radius;\r\n const newRadius = Clamp(requestedRadius, this.limits.radiusMin, this.limits.radiusMax);\r\n const actualRadiusChange = newRadius - this._radius;\r\n const actualDistanceChange = hasRadialComponent ? actualRadiusChange / directionDotLookAt : 0;\r\n\r\n // Use this to compute new camera position and new center position.\r\n const newCameraPosition = this._position.add(zoomVector.scale(-actualDistanceChange));\r\n const newCenter = newCameraPosition.add(this._lookAtVector.scaleToRef(newRadius, TmpVectors.Vector3[3]));\r\n\r\n // Rescale new center to maintain same altitude as the old center.\r\n const currentCenterRadius = this._center.length();\r\n const newCenterRadius = newCenter.length();\r\n const newCenterRescale = currentCenterRadius / newCenterRadius;\r\n newCenter.scaleInPlace(newCenterRescale);\r\n\r\n // Copy new center to ref\r\n Vector3CopyToRef(newCenter, centerRef);\r\n\r\n // Return new radius\r\n return newRadius;\r\n }\r\n\r\n private _applyZoom(zoomVector: Vector3, distance: number) {\r\n const newRadius = this._getRadiusAndCenterFromZoomTowards(zoomVector, distance, this._tempVect);\r\n\r\n // Apply changes\r\n this._setOrientation(this._yaw, this._pitch, newRadius, this._tempVect);\r\n }\r\n\r\n override _checkInputs(): void {\r\n this.inputs.checkInputs();\r\n\r\n // Let movement class handle all per-frame logic\r\n this.movement.computeCurrentFrameDeltas();\r\n\r\n if (this.movement.panDeltaCurrentFrame.lengthSquared() > 0) {\r\n this._applyGeocentricTranslation();\r\n this._isViewMatrixDirty = true;\r\n }\r\n if (this.movement.rotationDeltaCurrentFrame.lengthSquared() > 0) {\r\n this._applyGeocentricRotation();\r\n this._isViewMatrixDirty = true;\r\n }\r\n\r\n if (Math.abs(this.movement.zoomDeltaCurrentFrame) > Epsilon) {\r\n this._applyZoom(this.movement.computedPerFrameZoomVector, this.movement.zoomDeltaCurrentFrame);\r\n this._isViewMatrixDirty = true;\r\n }\r\n\r\n super._checkInputs();\r\n }\r\n\r\n override attachControl(noPreventDefault?: boolean): void {\r\n this.inputs.attachElement(noPreventDefault);\r\n }\r\n\r\n override detachControl(): void {\r\n this.inputs.detachElement();\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"geospatialCamera.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/geospatialCamera.ts"],"names":[],"mappings":"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","sourcesContent":["import { GeospatialCameraInputsManager } from \"./geospatialCameraInputsManager\";\r\nimport { Vector3, Matrix, TmpVectors } from \"../Maths/math.vector\";\r\nimport { Epsilon } from \"../Maths/math.constants\";\r\nimport { Camera } from \"./camera\";\r\nimport type { Scene } from \"../scene\";\r\nimport type { MeshPredicate } from \"../Culling/ray.core\";\r\nimport type { DeepImmutable } from \"../types\";\r\nimport { GeospatialLimits } from \"./Limits/geospatialLimits\";\r\nimport { ClampCenterFromPolesInPlace, ComputeLocalBasisToRefs, GeospatialCameraMovement } from \"./geospatialCameraMovement\";\r\nimport type { IVector3Like } from \"../Maths/math.like\";\r\nimport { Vector3CopyToRef } from \"../Maths/math.vector.functions\";\r\nimport { Clamp } from \"../Maths/math.scalar.functions\";\r\nimport type { AllowedAnimValue } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\nimport { InterpolatingBehavior } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\nimport type { EasingFunction } from \"../Animations/easing\";\r\n\r\ntype CameraOptions = {\r\n planetRadius: number; // Radius of the planet\r\n};\r\n\r\n/**\r\n * @experimental\r\n * This camera's movements are limited to a camera orbiting a globe, and as the API evolves it will introduce conversions between cartesian coordinates and true lat/long/alt\r\n *\r\n * Please note this is marked as experimental and the API (including the constructor!) will change until we remove that flag\r\n */\r\nexport class GeospatialCamera extends Camera {\r\n override inputs: GeospatialCameraInputsManager;\r\n\r\n /** If supplied, will be used when picking the globe */\r\n public pickPredicate?: MeshPredicate;\r\n\r\n /** Movement controller that turns input pixelDeltas into currentFrameDeltas used by camera*/\r\n public readonly movement: GeospatialCameraMovement;\r\n\r\n // Temp vars\r\n private _tempPosition: Vector3 = new Vector3();\r\n private _tempCenter: Vector3 = new Vector3();\r\n\r\n private _viewMatrix = new Matrix();\r\n private _isViewMatrixDirty: boolean;\r\n private _lookAtVector: Vector3 = new Vector3();\r\n\r\n /** Behavior used for smooth flying animations */\r\n private _flyingBehavior: InterpolatingBehavior<GeospatialCamera>;\r\n private _flyToTargets: Map<keyof GeospatialCamera, AllowedAnimValue> = new Map();\r\n\r\n constructor(name: string, scene: Scene, options: CameraOptions, pickPredicate?: MeshPredicate) {\r\n super(name, new Vector3(), scene);\r\n\r\n this._limits = new GeospatialLimits(options.planetRadius);\r\n this._resetToDefault(this._limits);\r\n\r\n this._flyingBehavior = new InterpolatingBehavior();\r\n this.addBehavior(this._flyingBehavior);\r\n\r\n this.movement = new GeospatialCameraMovement(scene, this._limits, this.position, this.center, this._lookAtVector, pickPredicate, this._flyingBehavior);\r\n\r\n this.pickPredicate = pickPredicate;\r\n this.inputs = new GeospatialCameraInputsManager(this);\r\n this.inputs.addMouse().addMouseWheel().addKeyboard();\r\n }\r\n\r\n private _center: Vector3 = new Vector3();\r\n /** The point on the globe that we are anchoring around. If no alternate rotation point is supplied, this will represent the center of screen*/\r\n public get center(): Vector3 {\r\n return this._center;\r\n }\r\n\r\n /**\r\n * Sets the camera position to orbit around a new center point\r\n * @param center The world position (ECEF) to orbit around\r\n */\r\n public set center(center: IVector3Like) {\r\n this._center.copyFromFloats(center.x, center.y, center.z);\r\n this._setOrientation(this._yaw, this._pitch, this._radius, this._center);\r\n }\r\n\r\n private _yaw: number = 0;\r\n /**\r\n * Gets the camera's yaw (rotation around the geocentric normal) in radians\r\n */\r\n public get yaw(): number {\r\n return this._yaw;\r\n }\r\n\r\n /**\r\n * Sets the camera's yaw (rotation around the geocentric normal)\r\n * @param yaw The desired yaw angle in radians (0 = north, π/2 = east)\r\n */\r\n public set yaw(yaw: number) {\r\n this._setOrientation(yaw, this.pitch, this.radius, this.center);\r\n }\r\n\r\n private _pitch: number = 0;\r\n\r\n /**\r\n * Gets the camera's pitch (angle from looking straight at globe)\r\n * Pitch is measured from looking straight down at planet center:\r\n * - zero pitch = looking straight at planet center (down)\r\n * - positive pitch = tilting up away from planet\r\n * - π/2 pitch = looking at horizon (perpendicular to geocentric normal)\r\n */\r\n public get pitch(): number {\r\n return this._pitch;\r\n }\r\n\r\n /**\r\n * Sets the camera's pitch (angle from looking straight at globe)\r\n * @param pitch The desired pitch angle in radians (0 = looking at planet center, π/2 = looking at horizon)\r\n */\r\n public set pitch(pitch: number) {\r\n this._setOrientation(this.yaw, pitch, this.radius, this.center);\r\n }\r\n\r\n private _radius: number = 0;\r\n public get radius(): number {\r\n return this._radius;\r\n }\r\n\r\n /**\r\n * Sets the camera's distance from the current center point\r\n * @param radius The desired radius\r\n */\r\n public set radius(radius: number) {\r\n this._setOrientation(this.yaw, this.pitch, radius, this.center);\r\n }\r\n\r\n protected _checkLimits() {\r\n const limits = this.limits;\r\n this._yaw = Clamp(this._yaw, limits.yawMin, limits.yawMax);\r\n this._pitch = Clamp(this._pitch, limits.pitchMin, limits.pitchMax);\r\n this._radius = Clamp(this._radius, limits.radiusMin, limits.radiusMax);\r\n this._center = ClampCenterFromPolesInPlace(this._center);\r\n }\r\n\r\n private _tempVect = new Vector3();\r\n private _tempEast = new Vector3();\r\n private _tempNorth = new Vector3();\r\n private _tempUp = new Vector3();\r\n\r\n private _setOrientation(yaw: number, pitch: number, radius: number, center: DeepImmutable<IVector3Like>): void {\r\n this._yaw = yaw;\r\n this._pitch = pitch;\r\n this._radius = radius;\r\n\r\n Vector3CopyToRef(center, this._center);\r\n\r\n // Clamp to limits\r\n this._checkLimits();\r\n\r\n // Refresh local basis at center (treat these as read-only for the whole call)\r\n ComputeLocalBasisToRefs(this._center, this._tempEast, this._tempNorth, this._tempUp);\r\n\r\n // Trig\r\n const yawScale = this._scene.useRightHandedSystem ? 1 : -1;\r\n const cosYaw = Math.cos(this._yaw * yawScale);\r\n const sinYaw = Math.sin(this._yaw * yawScale);\r\n const sinPitch = Math.sin(this._pitch); // horizontal weight\r\n const cosPitch = Math.cos(this._pitch); // vertical weight (toward center)\r\n\r\n // Temps\r\n const horiz = TmpVectors.Vector3[0];\r\n const t1 = TmpVectors.Vector3[1];\r\n const t2 = TmpVectors.Vector3[2];\r\n const right = TmpVectors.Vector3[3];\r\n\r\n // horizontalDirection = North*cosYaw + East*sinYaw (avoids mutating _temp basis vectors)\r\n horiz.copyFrom(this._tempNorth).scaleInPlace(cosYaw).addInPlace(t1.copyFrom(this._tempEast).scaleInPlace(sinYaw));\r\n\r\n // look = horiz*sinPitch - Up*cosPitch\r\n this._lookAtVector.copyFrom(horiz).scaleInPlace(sinPitch).addInPlace(t2.copyFrom(this._tempUp).scaleInPlace(-cosPitch)).normalize(); // keep it unit\r\n\r\n // Build an orthonormal up aligned with geocentric Up\r\n // right = normalize(cross(upRef, look))\r\n Vector3.CrossToRef(this._tempUp, this._lookAtVector, right);\r\n\r\n // up = normalize(cross(look, right))\r\n Vector3.CrossToRef(this._lookAtVector, right, this.upVector);\r\n\r\n // Position = center - look * radius (preserve unit look)\r\n this._tempVect.copyFrom(this._lookAtVector).scaleInPlace(-this._radius);\r\n this._tempPosition.copyFrom(this._center).addInPlace(this._tempVect);\r\n\r\n this._position.copyFrom(this._tempPosition);\r\n\r\n this._isViewMatrixDirty = true;\r\n }\r\n\r\n /** The point around which the camera will geocentrically rotate. Uses center (pt we are anchored to) if no alternateRotationPt is defined */\r\n private get _geocentricRotationPt(): Vector3 {\r\n return this.movement.alternateRotationPt ?? this.center;\r\n }\r\n\r\n /**\r\n * If camera is actively in flight, will update the target properties and use up the remaining duration from original flyTo call\r\n *\r\n * To start a new flyTo curve entirely, call into flyToAsync again (it will stop the inflight animation)\r\n * @param targetYaw\r\n * @param targetPitch\r\n * @param targetRadius\r\n * @param targetCenter\r\n */\r\n public updateFlyToDestination(targetYaw?: number, targetPitch?: number, targetRadius?: number, targetCenter?: Vector3): void {\r\n this._flyToTargets.clear();\r\n\r\n this._flyToTargets.set(\"yaw\", targetYaw);\r\n this._flyToTargets.set(\"pitch\", targetPitch);\r\n this._flyToTargets.set(\"radius\", targetRadius);\r\n this._flyToTargets.set(\"center\", targetCenter);\r\n\r\n this._flyingBehavior.updateProperties(this._flyToTargets);\r\n }\r\n\r\n private _customKeys = new Map();\r\n /**\r\n * Animate camera towards passed in property values. If undefined, will use current value\r\n * @param targetYaw\r\n * @param targetPitch\r\n * @param targetRadius\r\n * @param targetCenter\r\n * @param flightDurationMs\r\n * @param easingFunction\r\n * @param overshootRadiusScale If defined, will first fly to radius*scale before flying to targetRadius to create a \"bounce\" effect\r\n * @returns Promise that will return when the animation is complete (or interuppted by pointer input)\r\n */\r\n public async flyToAsync(\r\n targetYaw?: number,\r\n targetPitch?: number,\r\n targetRadius?: number,\r\n targetCenter?: Vector3,\r\n flightDurationMs: number = 1000,\r\n easingFunction?: EasingFunction,\r\n overshootRadiusScale?: number\r\n ): Promise<void> {\r\n this._flyToTargets.clear();\r\n this._customKeys.clear();\r\n\r\n this._flyToTargets.set(\"yaw\", targetYaw);\r\n this._flyToTargets.set(\"pitch\", targetPitch);\r\n this._flyToTargets.set(\"radius\", targetRadius);\r\n this._flyToTargets.set(\"center\", targetCenter);\r\n\r\n const overshootRadius = overshootRadiusScale !== undefined ? this.radius * overshootRadiusScale : undefined;\r\n if (overshootRadius !== undefined && overshootRadius !== targetRadius) {\r\n // Start the animation with overshoot radius\r\n const frameRate = 60;\r\n const totalFrames = (flightDurationMs / 1000) * frameRate;\r\n const midFrame = totalFrames / 2;\r\n\r\n this._customKeys.set(\"radius\", [\r\n { frame: 0, value: this.radius },\r\n { frame: midFrame, value: overshootRadius },\r\n { frame: totalFrames, value: targetRadius },\r\n ]);\r\n }\r\n return await this._flyingBehavior.animatePropertiesAsync(this._flyToTargets, flightDurationMs, easingFunction, this._customKeys);\r\n }\r\n\r\n /**\r\n * Helper function to move camera towards a given point by radiusScale% of radius (by default 50%)\r\n * @param destination point to move towards\r\n * @param radiusScale value between 0 and 1, % of radius to move\r\n * @param durationMs duration of flight, default 1s\r\n * @param easingFn optional easing function for flight interpolation of properties\r\n * @param overshootRadiusScale optional scale to apply to the current radius to achieve a 'hop' animation\r\n */\r\n public async flyToPointAsync(destination: Vector3, radiusScale: number = 0.5, durationMs: number = 1000, easingFn?: EasingFunction, overshootRadiusScale?: number) {\r\n // Zoom to radiusScale% of radius towards the given destination point\r\n const zoomDistance = this.radius * radiusScale;\r\n const newRadius = this._getCenterAndRadiusFromZoomToPoint(destination, zoomDistance, this._tempCenter);\r\n await this.flyToAsync(undefined, undefined, newRadius, this._tempCenter, durationMs, easingFn, overshootRadiusScale);\r\n }\r\n\r\n private _limits: GeospatialLimits;\r\n public get limits(): GeospatialLimits {\r\n return this._limits;\r\n }\r\n\r\n private _resetToDefault(limits: GeospatialLimits): void {\r\n // Camera configuration vars\r\n const maxCameraRadius = limits.altitudeMax !== undefined ? limits.planetRadius + limits.altitudeMax : undefined;\r\n const restingAltitude = maxCameraRadius ?? limits.planetRadius * 4;\r\n this.position.copyFromFloats(restingAltitude, 0, 0);\r\n this._center.copyFromFloats(limits.planetRadius, 0, 0);\r\n this._radius = Vector3.Distance(this.position, this.center);\r\n\r\n // Temp vars\r\n this._tempPosition = new Vector3();\r\n\r\n // View matrix calculation vars\r\n this._viewMatrix = Matrix.Identity();\r\n this._center.subtractToRef(this._position, this._lookAtVector).normalize(); // Lookat vector of the camera\r\n this.upVector = Vector3.Up(); // Up vector of the camera (does work for -X look at)\r\n this._isViewMatrixDirty = true;\r\n\r\n this._setOrientation(this._yaw, this._pitch, this._radius, this._center);\r\n }\r\n\r\n /** @internal */\r\n override _getViewMatrix() {\r\n if (!this._isViewMatrixDirty) {\r\n return this._viewMatrix;\r\n }\r\n this._isViewMatrixDirty = false;\r\n\r\n // Ensure vectors are normalized\r\n this.upVector.normalize();\r\n this._lookAtVector.normalize();\r\n\r\n // Calculate view matrix with camera position and center\r\n if (this.getScene().useRightHandedSystem) {\r\n Matrix.LookAtRHToRef(this.position, this._center, this.upVector, this._viewMatrix);\r\n } else {\r\n Matrix.LookAtLHToRef(this.position, this._center, this.upVector, this._viewMatrix);\r\n }\r\n\r\n return this._viewMatrix;\r\n }\r\n\r\n /** @internal */\r\n override _isSynchronizedViewMatrix(): boolean {\r\n if (!super._isSynchronizedViewMatrix() || this._isViewMatrixDirty) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n private _applyGeocentricTranslation() {\r\n // Store pending position (without any corrections applied)\r\n this.center.addToRef(this.movement.panDeltaCurrentFrame, this._tempPosition);\r\n\r\n if (!this.movement.isInterpolating) {\r\n // Calculate the position correction to keep camera at the same radius when applying translation\r\n this._tempPosition.normalize().scaleInPlace(this.center.length());\r\n }\r\n // Set center which will call _setOrientation\r\n this.center = this._tempPosition;\r\n }\r\n\r\n /**\r\n * This rotation keeps the camera oriented towards the globe as it orbits around it. This is different from cameraCentricRotation which is when the camera rotates around its own axis\r\n */\r\n private _applyGeocentricRotation(): void {\r\n const rotationDeltaCurrentFrame = this.movement.rotationDeltaCurrentFrame;\r\n if (rotationDeltaCurrentFrame.x !== 0 || rotationDeltaCurrentFrame.y !== 0) {\r\n const pitch = rotationDeltaCurrentFrame.x !== 0 ? Clamp(this._pitch + rotationDeltaCurrentFrame.x, 0, 0.5 * Math.PI - Epsilon) : this._pitch;\r\n const yaw = rotationDeltaCurrentFrame.y !== 0 ? this._yaw + rotationDeltaCurrentFrame.y : this._yaw;\r\n\r\n // TODO: If _geocentricRotationPt is not the center, this will need to be adjusted.\r\n this._setOrientation(yaw, pitch, this._radius, this._geocentricRotationPt);\r\n }\r\n }\r\n\r\n private _getCenterAndRadiusFromZoomToPoint(targetPoint: Vector3, distance: number, newCenter: Vector3): number {\r\n // Clamp new radius to limits\r\n const requestedRadius = this._radius - distance;\r\n const newRadius = Clamp(requestedRadius, this.limits.radiusMin, this.limits.radiusMax);\r\n const actualDistance = this._radius - newRadius;\r\n const actualRatio = actualDistance / this._radius;\r\n\r\n // Direction from current center to target point\r\n const directionToTarget = TmpVectors.Vector3[0];\r\n targetPoint.subtractToRef(this._center, directionToTarget);\r\n\r\n // Move center toward target by the ratio amount\r\n const centerOffset = TmpVectors.Vector3[1];\r\n directionToTarget.scaleToRef(actualRatio, centerOffset);\r\n\r\n // Calculate new center\r\n this._center.addToRef(centerOffset, newCenter);\r\n\r\n // Preserve center altitude (distance from planet origin)\r\n const currentCenterRadius = this._center.length();\r\n const newCenterRadius = newCenter.length();\r\n if (newCenterRadius > Epsilon) {\r\n newCenter.scaleInPlace(currentCenterRadius / newCenterRadius);\r\n }\r\n\r\n return newRadius;\r\n }\r\n\r\n /**\r\n * Apply zoom by moving the camera toward/away from a target point.\r\n */\r\n private _applyZoom() {\r\n const zoomDelta = this.movement.zoomDeltaCurrentFrame;\r\n const pickedPoint = this.movement.computedPerFrameZoomPickPoint;\r\n\r\n if (pickedPoint) {\r\n // Zoom toward the picked point under cursor\r\n this._zoomToPoint(pickedPoint, zoomDelta);\r\n } else {\r\n // Zoom along lookAt vector (fallback when no surface under cursor)\r\n this._zoomAlongLookAt(zoomDelta);\r\n }\r\n }\r\n\r\n private _zoomToPoint(targetPoint: Vector3, distance: number) {\r\n const newRadius = this._getCenterAndRadiusFromZoomToPoint(targetPoint, distance, this._tempCenter);\r\n // Apply the new orientation\r\n this._setOrientation(this._yaw, this._pitch, newRadius, this._tempCenter);\r\n }\r\n\r\n private _zoomAlongLookAt(distance: number) {\r\n // Clamp radius to limits\r\n const requestedRadius = this._radius - distance;\r\n const newRadius = Clamp(requestedRadius, this.limits.radiusMin, this.limits.radiusMax);\r\n\r\n // Simply change radius without moving center\r\n this._setOrientation(this._yaw, this._pitch, newRadius, this._center);\r\n }\r\n\r\n override _checkInputs(): void {\r\n this.inputs.checkInputs();\r\n\r\n // Let movement class handle all per-frame logic\r\n this.movement.computeCurrentFrameDeltas();\r\n\r\n let recalculateCenter = false;\r\n if (this.movement.panDeltaCurrentFrame.lengthSquared() > 0) {\r\n this._applyGeocentricTranslation();\r\n recalculateCenter = true;\r\n }\r\n if (this.movement.rotationDeltaCurrentFrame.lengthSquared() > 0) {\r\n this._applyGeocentricRotation();\r\n }\r\n\r\n if (Math.abs(this.movement.zoomDeltaCurrentFrame) > Epsilon) {\r\n this._applyZoom();\r\n recalculateCenter = true;\r\n }\r\n\r\n // After a movement impacting center or radius, recalculate the center point to ensure it's still on the surface.\r\n recalculateCenter && this._recalculateCenter();\r\n\r\n super._checkInputs();\r\n }\r\n\r\n private _recalculateCenter() {\r\n // Wait until dragging is complete to avoid wasted raycasting\r\n if (!this.movement.isDragging) {\r\n const newCenter = this.movement.pickAlongVector(this._lookAtVector);\r\n if (newCenter?.pickedPoint) {\r\n // Direction from new center to origin\r\n const centerToOrigin = TmpVectors.Vector3[4];\r\n centerToOrigin.copyFrom(newCenter.pickedPoint).negateInPlace().normalize();\r\n\r\n // Check if this direction aligns with camera's lookAt vector\r\n const dotProduct = Vector3.Dot(this._lookAtVector, centerToOrigin);\r\n\r\n // Only update if the center is looking toward the origin (dot product > 0) to avoid a center on the opposite side of globe\r\n if (dotProduct > 0) {\r\n const newRadius = Vector3.Distance(this.position, newCenter.pickedPoint);\r\n this._setOrientation(this._yaw, this._pitch, newRadius, newCenter.pickedPoint);\r\n }\r\n }\r\n }\r\n }\r\n override attachControl(noPreventDefault?: boolean): void {\r\n this.inputs.attachElement(noPreventDefault);\r\n }\r\n\r\n override detachControl(): void {\r\n this.inputs.detachElement();\r\n }\r\n}\r\n"]}
|
|
@@ -5,6 +5,8 @@ import type { MeshPredicate } from "../Culling/ray.core.js";
|
|
|
5
5
|
import type { Scene } from "../scene.js";
|
|
6
6
|
import type { PickingInfo } from "../Collisions/pickingInfo.js";
|
|
7
7
|
import type { Nullable } from "../types.js";
|
|
8
|
+
import type { InterpolatingBehavior } from "../Behaviors/Cameras/interpolatingBehavior.js";
|
|
9
|
+
import type { GeospatialCamera } from "./geospatialCamera.js";
|
|
8
10
|
/**
|
|
9
11
|
* @experimental
|
|
10
12
|
* This class is subject to change as the geospatial camera evolves.
|
|
@@ -26,7 +28,8 @@ export declare class GeospatialCameraMovement extends CameraMovement {
|
|
|
26
28
|
private _cameraLookAt;
|
|
27
29
|
/** Predicate function to determine which meshes to pick against (e.g., globe mesh) */
|
|
28
30
|
pickPredicate?: MeshPredicate;
|
|
29
|
-
|
|
31
|
+
/** World-space picked point under cursor for zoom-to-cursor behavior (may be undefined) */
|
|
32
|
+
computedPerFrameZoomPickPoint?: Vector3;
|
|
30
33
|
zoomToCursor: boolean;
|
|
31
34
|
/**
|
|
32
35
|
* Enables rotation around a specific point, instead of default rotation around center
|
|
@@ -41,7 +44,7 @@ export declare class GeospatialCameraMovement extends CameraMovement {
|
|
|
41
44
|
private _dragPlaneOriginPointEcef;
|
|
42
45
|
private _dragPlaneHitPointLocal;
|
|
43
46
|
private _previousDragPlaneHitPointLocal;
|
|
44
|
-
constructor(scene: Scene, limits: GeospatialLimits, cameraPosition: Vector3, _cameraCenter: Vector3, _cameraLookAt: Vector3, pickPredicate?: MeshPredicate);
|
|
47
|
+
constructor(scene: Scene, limits: GeospatialLimits, cameraPosition: Vector3, _cameraCenter: Vector3, _cameraLookAt: Vector3, pickPredicate?: MeshPredicate, behavior?: InterpolatingBehavior<GeospatialCamera>);
|
|
45
48
|
startDrag(pointerX: number, pointerY: number): void;
|
|
46
49
|
stopDrag(): void;
|
|
47
50
|
/**
|
|
@@ -55,6 +58,7 @@ export declare class GeospatialCameraMovement extends CameraMovement {
|
|
|
55
58
|
handleDrag(pointerX: number, pointerY: number): void;
|
|
56
59
|
/** @override */
|
|
57
60
|
computeCurrentFrameDeltas(): void;
|
|
61
|
+
get isDragging(): boolean;
|
|
58
62
|
private _handleZoom;
|
|
59
63
|
private _clampZoomDistance;
|
|
60
64
|
pickAlongVector(vector: Vector3): Nullable<PickingInfo>;
|
|
@@ -21,12 +21,11 @@ import { Clamp } from "../Maths/math.scalar.functions.js";
|
|
|
21
21
|
* - Zoom direction calculation (towards cursor vs along look vector)
|
|
22
22
|
*/
|
|
23
23
|
export class GeospatialCameraMovement extends CameraMovement {
|
|
24
|
-
constructor(scene, limits, cameraPosition, _cameraCenter, _cameraLookAt, pickPredicate) {
|
|
25
|
-
super(scene, cameraPosition);
|
|
24
|
+
constructor(scene, limits, cameraPosition, _cameraCenter, _cameraLookAt, pickPredicate, behavior) {
|
|
25
|
+
super(scene, cameraPosition, behavior);
|
|
26
26
|
this.limits = limits;
|
|
27
27
|
this._cameraCenter = _cameraCenter;
|
|
28
28
|
this._cameraLookAt = _cameraLookAt;
|
|
29
|
-
this.computedPerFrameZoomVector = new Vector3();
|
|
30
29
|
this.zoomToCursor = true;
|
|
31
30
|
this._hitPointRadius = undefined;
|
|
32
31
|
this._dragPlane = new Plane(0, 0, 0, 0);
|
|
@@ -34,7 +33,6 @@ export class GeospatialCameraMovement extends CameraMovement {
|
|
|
34
33
|
this._dragPlaneOriginPointEcef = Vector3.Zero();
|
|
35
34
|
this._dragPlaneHitPointLocal = Vector3.Zero();
|
|
36
35
|
this._previousDragPlaneHitPointLocal = Vector3.Zero();
|
|
37
|
-
this.computedPerFrameZoomVector.copyFrom(this._cameraLookAt);
|
|
38
36
|
this.pickPredicate = pickPredicate;
|
|
39
37
|
this._tempPickingRay = new Ray(this._cameraPosition, this._cameraLookAt);
|
|
40
38
|
this.panInertia = 0;
|
|
@@ -115,8 +113,7 @@ export class GeospatialCameraMovement extends CameraMovement {
|
|
|
115
113
|
this._panSpeedMultiplier = 1;
|
|
116
114
|
}
|
|
117
115
|
// If a pan drag is occurring, stop zooming.
|
|
118
|
-
|
|
119
|
-
if (isDragging) {
|
|
116
|
+
if (this.isDragging) {
|
|
120
117
|
this._zoomSpeedMultiplier = 0;
|
|
121
118
|
this._zoomVelocity = 0;
|
|
122
119
|
}
|
|
@@ -129,6 +126,9 @@ export class GeospatialCameraMovement extends CameraMovement {
|
|
|
129
126
|
super.computeCurrentFrameDeltas();
|
|
130
127
|
this._handleZoom(activeZoom);
|
|
131
128
|
}
|
|
129
|
+
get isDragging() {
|
|
130
|
+
return this._hitPointRadius !== undefined;
|
|
131
|
+
}
|
|
132
132
|
_handleZoom(activeZoom) {
|
|
133
133
|
if (Math.abs(this.zoomDeltaCurrentFrame) > Epsilon) {
|
|
134
134
|
let pickDistance;
|
|
@@ -141,17 +141,17 @@ export class GeospatialCameraMovement extends CameraMovement {
|
|
|
141
141
|
// Active zoom - pick and store the distance
|
|
142
142
|
const pickResult = this._scene.pick(this._scene.pointerX, this._scene.pointerY, this.pickPredicate);
|
|
143
143
|
if (pickResult.hit && pickResult.pickedPoint && pickResult.ray && this.zoomToCursor) {
|
|
144
|
-
// Store both the zoom
|
|
145
|
-
pickResult.ray.direction.normalizeToRef(this.computedPerFrameZoomVector);
|
|
144
|
+
// Store both the zoom picked point and the pick distance for use during inertia
|
|
146
145
|
pickDistance = pickResult.distance;
|
|
147
146
|
this._storedZoomPickDistance = pickDistance;
|
|
147
|
+
this.computedPerFrameZoomPickPoint = pickResult.pickedPoint;
|
|
148
148
|
}
|
|
149
149
|
else {
|
|
150
150
|
// If no hit under cursor, zoom along lookVector instead
|
|
151
|
-
this.
|
|
152
|
-
const lookPickResult = this.pickAlongVector(this.computedPerFrameZoomVector);
|
|
151
|
+
const lookPickResult = this.pickAlongVector(this._cameraLookAt);
|
|
153
152
|
pickDistance = lookPickResult?.distance;
|
|
154
153
|
this._storedZoomPickDistance = pickDistance;
|
|
154
|
+
this.computedPerFrameZoomPickPoint = undefined;
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
// Clamp distance based on limits and update center
|