@@ -8,11 +8,12 @@ import type { DeepImmutable } from "../types";
88import { GeospatialLimits } from "./Limits/geospatialLimits" ;
99import { ClampCenterFromPolesInPlace , ComputeLocalBasisToRefs , GeospatialCameraMovement } from "./geospatialCameraMovement" ;
1010import type { IVector3Like } from "../Maths/math.like" ;
11- import { Vector3CopyToRef } from "../Maths/math.vector.functions" ;
11+ import { Vector3CopyToRef , Vector3Distance } from "../Maths/math.vector.functions" ;
1212import { Clamp } from "../Maths/math.scalar.functions" ;
1313import type { AllowedAnimValue } from "../Behaviors/Cameras/interpolatingBehavior" ;
1414import { InterpolatingBehavior } from "../Behaviors/Cameras/interpolatingBehavior" ;
1515import type { EasingFunction } from "../Animations/easing" ;
16+ import type { Animation } from "../Animations/animation" ;
1617
1718type CameraOptions = {
1819 planetRadius : number ; // Radius of the planet
@@ -212,7 +213,6 @@ export class GeospatialCamera extends Camera {
212213 this . _flyingBehavior . updateProperties ( this . _flyToTargets ) ;
213214 }
214215
215- private _customKeys = new Map ( ) ;
216216 /**
217217 * Animate camera towards passed in property values. If undefined, will use current value
218218 * @param targetYaw
@@ -221,7 +221,7 @@ export class GeospatialCamera extends Camera {
221221 * @param targetCenter
222222 * @param flightDurationMs
223223 * @param easingFunction
224- * @param overshootRadiusScale If defined , will first fly to radius*scale before flying to targetRadius to create a "bounce" effect
224+ * @param centerHopScale If supplied , will define the parabolic hop height scale for center animation to create a "bounce" effect
225225 * @returns Promise that will return when the animation is complete (or interuppted by pointer input)
226226 */
227227 public async flyToAsync (
@@ -231,30 +231,47 @@ export class GeospatialCamera extends Camera {
231231 targetCenter ?: Vector3 ,
232232 flightDurationMs : number = 1000 ,
233233 easingFunction ?: EasingFunction ,
234- overshootRadiusScale ?: number
234+ centerHopScale ?: number
235235 ) : Promise < void > {
236236 this . _flyToTargets . clear ( ) ;
237- this . _customKeys . clear ( ) ;
238237
239238 this . _flyToTargets . set ( "yaw" , targetYaw ) ;
240239 this . _flyToTargets . set ( "pitch" , targetPitch ) ;
241240 this . _flyToTargets . set ( "radius" , targetRadius ) ;
242241 this . _flyToTargets . set ( "center" , targetCenter ) ;
243242
244- const overshootRadius = overshootRadiusScale !== undefined ? this . radius * overshootRadiusScale : undefined ;
245- if ( overshootRadius !== undefined && overshootRadius !== targetRadius ) {
246- // Start the animation with overshoot radius
247- const frameRate = 60 ;
248- const totalFrames = ( flightDurationMs / 1000 ) * frameRate ;
249- const midFrame = totalFrames / 2 ;
250-
251- this . _customKeys . set ( "radius" , [
252- { frame : 0 , value : this . radius } ,
253- { frame : midFrame , value : overshootRadius } ,
254- { frame : totalFrames , value : targetRadius } ,
255- ] ) ;
243+ let overrideAnimationFunction ;
244+ if ( targetCenter !== undefined && ! targetCenter . equals ( this . center ) ) {
245+ // Animate center directly with custom interpolation
246+ const start = this . center . clone ( ) ;
247+ const end = targetCenter . clone ( ) ;
248+
249+ overrideAnimationFunction = ( key : string , animation : Animation ) : void => {
250+ if ( key === "center" ) {
251+ // Override the Vector3 interpolation to use SLERP + hop
252+ animation . vector3InterpolateFunction = ( startValue , endValue , gradient ) => {
253+ // gradient is the eased value (0 to 1) after easing function is applied
254+
255+ // Slerp between start and end
256+ const newCenter = Vector3 . SlerpToRef ( start , end , gradient , this . _tempCenter ) ;
257+
258+ // Apply parabolic hop if requested
259+ if ( centerHopScale && centerHopScale > 0 ) {
260+ // Parabolic formula: peaks at t=0.5, returns to 0 at gradient=0 and gradient=1
261+ // if hopPeakT = .5 the denominator would be hopPeakT * hopPeakT - hopPeakT, which = -.25
262+ const hopPeakOffset = centerHopScale * Vector3Distance ( start , end ) ;
263+ const hopOffset = hopPeakOffset * Clamp ( ( gradient * gradient - gradient ) / - 0.25 ) ;
264+ // Scale the center outward (away from origin)
265+ newCenter . scaleInPlace ( 1 + hopOffset / newCenter . length ( ) ) ;
266+ }
267+
268+ return newCenter ;
269+ } ;
270+ }
271+ } ;
256272 }
257- return await this . _flyingBehavior . animatePropertiesAsync ( this . _flyToTargets , flightDurationMs , easingFunction , this . _customKeys ) ;
273+
274+ return await this . _flyingBehavior . animatePropertiesAsync ( this . _flyToTargets , flightDurationMs , easingFunction , overrideAnimationFunction ) ;
258275 }
259276
260277 /**
0 commit comments