@@ -10,6 +10,9 @@ import { ComputeLocalBasisToRefs, GeospatialCameraMovement } from "./geospatialC
1010import type { IVector3Like } from "../Maths/math.like" ;
1111import { Vector3CopyToRef , Vector3Dot } from "../Maths/math.vector.functions" ;
1212import { Clamp } from "../Maths/math.scalar.functions" ;
13+ import type { AllowedAnimValue } from "../Behaviors/Cameras/interpolatingBehavior" ;
14+ import { InterpolatingBehavior } from "../Behaviors/Cameras/interpolatingBehavior" ;
15+ import type { EasingFunction } from "../Animations/easing" ;
1316
1417type CameraOptions = {
1518 planetRadius : number ; // Radius of the planet
@@ -37,12 +40,19 @@ export class GeospatialCamera extends Camera {
3740 private _isViewMatrixDirty : boolean ;
3841 private _lookAtVector : Vector3 = new Vector3 ( ) ;
3942
43+ /** Behavior used for smooth flying animations */
44+ private _flyingBehavior : InterpolatingBehavior < GeospatialCamera > ;
45+ private _flyToTargets : Map < keyof GeospatialCamera , AllowedAnimValue > = new Map ( ) ;
46+
4047 constructor ( name : string , scene : Scene , options : CameraOptions , pickPredicate ?: MeshPredicate ) {
4148 super ( name , new Vector3 ( ) , scene ) ;
4249
4350 this . _limits = new GeospatialLimits ( options . planetRadius ) ;
4451 this . _resetToDefault ( this . _limits ) ;
4552
53+ this . _flyingBehavior = new InterpolatingBehavior ( ) ;
54+ this . addBehavior ( this . _flyingBehavior ) ;
55+
4656 this . movement = new GeospatialCameraMovement ( scene , this . _limits , this . position , this . center , this . _lookAtVector , pickPredicate ) ;
4757
4858 this . pickPredicate = pickPredicate ;
@@ -51,7 +61,7 @@ export class GeospatialCamera extends Camera {
5161 }
5262
5363 private _center : Vector3 = new Vector3 ( ) ;
54- /** The point on the globe that we are anchoring around. If no alternate rotation point is present , this will represent the center of screen*/
64+ /** The point on the globe that we are anchoring around. If no alternate rotation point is supplied , this will represent the center of screen*/
5565 public get center ( ) : Vector3 {
5666 return this . _center ;
5767 }
@@ -180,6 +190,54 @@ export class GeospatialCamera extends Camera {
180190 return this . movement . alternateRotationPt ?? this . center ;
181191 }
182192
193+ /**
194+ * If camera is actively in flight, will update the target properties and use up the remaining duration from original flyTo call
195+ *
196+ * To start a new flyTo curve entirely, call into flyToAsync again (it will stop the inflight animation)
197+ * @param targetYaw
198+ * @param targetPitch
199+ * @param targetRadius
200+ * @param targetCenter
201+ */
202+ public updateFlyToDestination ( targetYaw ?: number , targetPitch ?: number , targetRadius ?: number , targetCenter ?: Vector3 ) : void {
203+ this . _flyToTargets . clear ( ) ;
204+
205+ this . _flyToTargets . set ( "yaw" , targetYaw ) ;
206+ this . _flyToTargets . set ( "pitch" , targetPitch ) ;
207+ this . _flyToTargets . set ( "radius" , targetRadius ) ;
208+ this . _flyToTargets . set ( "center" , targetCenter ) ;
209+
210+ this . _flyingBehavior . updateProperties ( this . _flyToTargets ) ;
211+ }
212+
213+ /**
214+ * Animate camera towards passed in property values. If undefined, will use current value
215+ * @param targetYaw
216+ * @param targetPitch
217+ * @param targetRadius
218+ * @param targetCenter
219+ * @param flightDurationMs
220+ * @param easingFunction
221+ * @returns Promise that will return when the animation is complete (or interuppted by pointer input)
222+ */
223+ public async flyToAsync (
224+ targetYaw ?: number ,
225+ targetPitch ?: number ,
226+ targetRadius ?: number ,
227+ targetCenter ?: Vector3 ,
228+ flightDurationMs : number = 1000 ,
229+ easingFunction ?: EasingFunction
230+ ) : Promise < void > {
231+ this . _flyToTargets . clear ( ) ;
232+
233+ this . _flyToTargets . set ( "yaw" , targetYaw ) ;
234+ this . _flyToTargets . set ( "pitch" , targetPitch ) ;
235+ this . _flyToTargets . set ( "radius" , targetRadius ) ;
236+ this . _flyToTargets . set ( "center" , targetCenter ) ;
237+
238+ return await this . _flyingBehavior . animatePropertiesAsync ( this . _flyToTargets , flightDurationMs , easingFunction ) ;
239+ }
240+
183241 private _limits : GeospatialLimits ;
184242 public get limits ( ) : GeospatialLimits {
185243 return this . _limits ;
@@ -250,10 +308,10 @@ export class GeospatialCamera extends Camera {
250308 * 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
251309 */
252310 private _applyGeocentricRotation ( ) : void {
253- const currentFrameRotationDelta = this . movement . rotationDeltaCurrentFrame ;
254- if ( currentFrameRotationDelta . x !== 0 || currentFrameRotationDelta . y !== 0 ) {
255- const pitch = currentFrameRotationDelta . x !== 0 ? Clamp ( this . _pitch + currentFrameRotationDelta . x , 0 , 0.5 * Math . PI - Epsilon ) : this . _pitch ;
256- const yaw = currentFrameRotationDelta . y !== 0 ? this . _yaw + currentFrameRotationDelta . y : this . _yaw ;
311+ const rotationDeltaCurrentFrame = this . movement . rotationDeltaCurrentFrame ;
312+ if ( rotationDeltaCurrentFrame . x !== 0 || rotationDeltaCurrentFrame . y !== 0 ) {
313+ const pitch = rotationDeltaCurrentFrame . x !== 0 ? Clamp ( this . _pitch + rotationDeltaCurrentFrame . x , 0 , 0.5 * Math . PI - Epsilon ) : this . _pitch ;
314+ const yaw = rotationDeltaCurrentFrame . y !== 0 ? this . _yaw + rotationDeltaCurrentFrame . y : this . _yaw ;
257315
258316 // TODO: If _geocentricRotationPt is not the center, this will need to be adjusted.
259317 this . _setOrientation ( yaw , pitch , this . _radius , this . _geocentricRotationPt ) ;
0 commit comments