@onerjs/core 8.33.3 → 8.33.4
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/AudioV2/webAudio/components/webAudioParameterComponent.js +17 -5
- package/AudioV2/webAudio/components/webAudioParameterComponent.js.map +1 -1
- package/Cameras/Inputs/geospatialCameraPointersInput.d.ts +2 -2
- package/Cameras/Inputs/geospatialCameraPointersInput.js +3 -12
- package/Cameras/Inputs/geospatialCameraPointersInput.js.map +1 -1
- package/Cameras/cameraMovement.d.ts +4 -4
- package/Cameras/cameraMovement.js +13 -14
- package/Cameras/cameraMovement.js.map +1 -1
- package/Cameras/geospatialCamera.d.ts +1 -2
- package/Cameras/geospatialCamera.js +22 -19
- package/Cameras/geospatialCamera.js.map +1 -1
- package/Cameras/geospatialCameraMovement.d.ts +0 -5
- package/Cameras/geospatialCameraMovement.js.map +1 -1
- package/Engines/abstractEngine.js +2 -2
- package/Engines/abstractEngine.js.map +1 -1
- package/FrameGraph/Tasks/Rendering/objectRendererTask.js +1 -2
- package/FrameGraph/Tasks/Rendering/objectRendererTask.js.map +1 -1
- package/FrameGraph/frameGraph.d.ts +6 -0
- package/FrameGraph/frameGraph.js +10 -0
- package/FrameGraph/frameGraph.js.map +1 -1
- package/Layers/glowLayer.d.ts +8 -0
- package/Layers/glowLayer.js +11 -0
- package/Layers/glowLayer.js.map +1 -1
- package/Layers/thinGlowLayer.d.ts +17 -0
- package/Layers/thinGlowLayer.js +18 -0
- package/Layers/thinGlowLayer.js.map +1 -1
- package/Lights/Clustered/clusteredLightContainer.js +7 -2
- package/Lights/Clustered/clusteredLightContainer.js.map +1 -1
- package/Materials/Node/Blocks/Dual/lightBlock.js +2 -1
- package/Materials/Node/Blocks/Dual/lightBlock.js.map +1 -1
- package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.js +2 -1
- package/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.js.map +1 -1
- package/Materials/Node/nodeMaterial.js +2 -2
- package/Materials/Node/nodeMaterial.js.map +1 -1
- package/Materials/PBR/pbrBaseMaterial.d.ts +1 -0
- package/Materials/PBR/pbrBaseMaterial.js +1 -0
- package/Materials/PBR/pbrBaseMaterial.js.map +1 -1
- package/Materials/Textures/envCubeTexture.js +4 -0
- package/Materials/Textures/envCubeTexture.js.map +1 -1
- package/Materials/materialHelper.functions.js +1 -0
- package/Materials/materialHelper.functions.js.map +1 -1
- package/Materials/standardMaterial.d.ts +1 -0
- package/Materials/standardMaterial.js +1 -0
- package/Materials/standardMaterial.js.map +1 -1
- package/Rendering/depthPeelingRenderer.d.ts +1 -0
- package/Rendering/depthPeelingRenderer.js +7 -0
- package/Rendering/depthPeelingRenderer.js.map +1 -1
- package/Rendering/thinDepthPeelingRenderer.d.ts +1 -0
- package/Rendering/thinDepthPeelingRenderer.js +2 -0
- package/Rendering/thinDepthPeelingRenderer.js.map +1 -1
- package/Shaders/default.vertex.js +4 -0
- package/Shaders/default.vertex.js.map +1 -1
- package/Shaders/lightProxy.vertex.js +7 -1
- package/Shaders/lightProxy.vertex.js.map +1 -1
- package/Shaders/pbr.vertex.js +4 -0
- package/Shaders/pbr.vertex.js.map +1 -1
- package/ShadersWGSL/default.vertex.js +4 -0
- package/ShadersWGSL/default.vertex.js.map +1 -1
- package/ShadersWGSL/lightProxy.vertex.js +7 -1
- package/ShadersWGSL/lightProxy.vertex.js.map +1 -1
- package/ShadersWGSL/pbr.vertex.js +4 -0
- package/ShadersWGSL/pbr.vertex.js.map +1 -1
- package/package.json +2 -5
- package/scene.js +2 -3
- package/scene.js.map +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Logger } from "../../../Misc/logger.js";
|
|
1
2
|
import { _GetAudioParamCurveValues } from "../../audioUtils.js";
|
|
2
3
|
/**
|
|
3
4
|
* Minimum duration in seconds for a ramp to be considered valid.
|
|
@@ -41,22 +42,33 @@ export class _WebAudioParameterComponent {
|
|
|
41
42
|
* @internal
|
|
42
43
|
*/
|
|
43
44
|
setTargetValue(value, options = null) {
|
|
45
|
+
if (!Number.isFinite(value)) {
|
|
46
|
+
Logger.Warn(`Attempted to set audio parameter to non-finite value: ${value}`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this._param.cancelScheduledValues(0);
|
|
44
50
|
const shape = typeof options?.shape === "string" ? options.shape : "linear" /* AudioParameterRampShape.Linear */;
|
|
45
51
|
const startTime = this._engine.currentTime;
|
|
46
52
|
if (shape === "none" /* AudioParameterRampShape.None */) {
|
|
47
|
-
this._param.cancelScheduledValues(0);
|
|
48
53
|
this._param.value = this._targetValue = value;
|
|
49
54
|
this._rampEndTime = startTime;
|
|
50
55
|
return;
|
|
51
56
|
}
|
|
52
57
|
let duration = typeof options?.duration === "number" ? Math.max(options.duration, this._engine.parameterRampDuration) : this._engine.parameterRampDuration;
|
|
58
|
+
this._targetValue = value;
|
|
53
59
|
if ((duration = Math.max(this._engine.parameterRampDuration, duration)) < MinRampDuration) {
|
|
54
|
-
this._param.setValueAtTime(
|
|
60
|
+
this._param.setValueAtTime(value, startTime);
|
|
55
61
|
return;
|
|
56
62
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
try {
|
|
64
|
+
this._param.setValueCurveAtTime(_GetAudioParamCurveValues(shape, Number.isFinite(this._param.value) ? this._param.value : 0, value), startTime, duration);
|
|
65
|
+
this._rampEndTime = startTime + duration;
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
Logger.Warn(`Audio parameter ramping failed. Setting value without ramping: ${e.message}`);
|
|
69
|
+
this._param.value = value;
|
|
70
|
+
this._rampEndTime = startTime;
|
|
71
|
+
}
|
|
60
72
|
}
|
|
61
73
|
}
|
|
62
74
|
//# sourceMappingURL=webAudioParameterComponent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webAudioParameterComponent.js","sourceRoot":"","sources":["../../../../../../dev/core/src/AudioV2/webAudio/components/webAudioParameterComponent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"webAudioParameterComponent.js","sourceRoot":"","sources":["../../../../../../dev/core/src/AudioV2/webAudio/components/webAudioParameterComponent.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger } from \"../../../Misc/logger\";\nimport type { Nullable } from \"../../../types\";\nimport type { IAudioParameterRampOptions } from \"../../audioParameter\";\nimport { AudioParameterRampShape } from \"../../audioParameter\";\nimport { _GetAudioParamCurveValues } from \"../../audioUtils\";\nimport type { _WebAudioEngine } from \"../webAudioEngine\";\n\n/**\n * Minimum duration in seconds for a ramp to be considered valid.\n *\n * If the duration is less than this value, the value will be set immediately instead of being ramped smoothly since\n * there is no perceptual difference for such short durations, so a ramp is not needed.\n */\nconst MinRampDuration = 0.000001;\n\n/** @internal */\nexport class _WebAudioParameterComponent {\n private _rampEndTime: number = 0;\n private _engine: _WebAudioEngine;\n private _param: AudioParam;\n private _targetValue: number;\n\n /** @internal */\n constructor(engine: _WebAudioEngine, param: AudioParam) {\n this._engine = engine;\n this._param = param;\n this._targetValue = param.value;\n }\n\n /** @internal */\n public get isRamping(): boolean {\n return this._engine.currentTime < this._rampEndTime;\n }\n\n /** @internal */\n public get targetValue(): number {\n return this._targetValue;\n }\n\n public set targetValue(value: number) {\n this.setTargetValue(value);\n }\n\n /** @internal */\n public get value(): number {\n return this._param.value;\n }\n\n /** @internal */\n public dispose(): void {\n this._param = null!;\n this._engine = null!;\n }\n\n /**\n * Sets the target value of the audio parameter with an optional ramping duration and shape.\n *\n * @internal\n */\n public setTargetValue(value: number, options: Nullable<Partial<IAudioParameterRampOptions>> = null): void {\n if (!Number.isFinite(value)) {\n Logger.Warn(`Attempted to set audio parameter to non-finite value: ${value}`);\n return;\n }\n\n this._param.cancelScheduledValues(0);\n\n const shape = typeof options?.shape === \"string\" ? options.shape : AudioParameterRampShape.Linear;\n const startTime = this._engine.currentTime;\n\n if (shape === AudioParameterRampShape.None) {\n this._param.value = this._targetValue = value;\n this._rampEndTime = startTime;\n return;\n }\n\n let duration = typeof options?.duration === \"number\" ? Math.max(options.duration, this._engine.parameterRampDuration) : this._engine.parameterRampDuration;\n\n this._targetValue = value;\n\n if ((duration = Math.max(this._engine.parameterRampDuration, duration)) < MinRampDuration) {\n this._param.setValueAtTime(value, startTime);\n return;\n }\n\n try {\n this._param.setValueCurveAtTime(_GetAudioParamCurveValues(shape, Number.isFinite(this._param.value) ? this._param.value : 0, value), startTime, duration);\n this._rampEndTime = startTime + duration;\n } catch (e) {\n Logger.Warn(`Audio parameter ramping failed. Setting value without ramping: ${(e as Error).message}`);\n this._param.value = value;\n this._rampEndTime = startTime;\n }\n }\n}\n"]}
|
|
@@ -12,8 +12,8 @@ import { OrbitCameraPointersInput } from "./orbitCameraPointersInput.js";
|
|
|
12
12
|
* As this is experimental, it is possible we move that correction step to live within the input class (to enable non-corrected translations in the future), say if we want to allow the camera to move outside of the globe's orbit
|
|
13
13
|
*
|
|
14
14
|
* Left mouse button: drag globe
|
|
15
|
-
* Middle mouse button: tilt globe
|
|
16
|
-
* Right mouse button: tilt globe
|
|
15
|
+
* Middle mouse button: tilt globe
|
|
16
|
+
* Right mouse button: tilt globe
|
|
17
17
|
*
|
|
18
18
|
*/
|
|
19
19
|
export declare class GeospatialCameraPointersInput extends OrbitCameraPointersInput {
|
|
@@ -8,8 +8,8 @@ import { OrbitCameraPointersInput } from "./orbitCameraPointersInput.js";
|
|
|
8
8
|
* As this is experimental, it is possible we move that correction step to live within the input class (to enable non-corrected translations in the future), say if we want to allow the camera to move outside of the globe's orbit
|
|
9
9
|
*
|
|
10
10
|
* Left mouse button: drag globe
|
|
11
|
-
* Middle mouse button: tilt globe
|
|
12
|
-
* Right mouse button: tilt globe
|
|
11
|
+
* Middle mouse button: tilt globe
|
|
12
|
+
* Right mouse button: tilt globe
|
|
13
13
|
*
|
|
14
14
|
*/
|
|
15
15
|
export class GeospatialCameraPointersInput extends OrbitCameraPointersInput {
|
|
@@ -19,20 +19,12 @@ export class GeospatialCameraPointersInput extends OrbitCameraPointersInput {
|
|
|
19
19
|
onButtonDown(evt) {
|
|
20
20
|
this.camera.movement.activeInput = true;
|
|
21
21
|
const scene = this.camera.getScene();
|
|
22
|
-
let pickResult;
|
|
23
22
|
switch (evt.button) {
|
|
24
23
|
case 0: // Left button - drag/pan globe under cursor
|
|
25
24
|
this.camera.movement.startDrag(scene.pointerX, scene.pointerY);
|
|
26
25
|
break;
|
|
27
|
-
case 1: // Middle button - tilt camera around cursor
|
|
28
|
-
pickResult = scene.pick(scene.pointerX, scene.pointerY, this.camera.pickPredicate);
|
|
29
|
-
pickResult.pickedPoint && (this.camera.movement.alternateRotationPt = pickResult.pickedPoint);
|
|
30
|
-
break;
|
|
31
|
-
case 2: // Right button - tilt camera around center of screen, already the default
|
|
32
|
-
this.camera.movement.alternateRotationPt = this.camera.center;
|
|
33
|
-
break;
|
|
34
26
|
default:
|
|
35
|
-
|
|
27
|
+
break;
|
|
36
28
|
}
|
|
37
29
|
}
|
|
38
30
|
onTouch(point, offsetX, offsetY) {
|
|
@@ -83,7 +75,6 @@ export class GeospatialCameraPointersInput extends OrbitCameraPointersInput {
|
|
|
83
75
|
}
|
|
84
76
|
onButtonUp(_evt) {
|
|
85
77
|
this.camera.movement.stopDrag();
|
|
86
|
-
this.camera.movement.alternateRotationPt = undefined;
|
|
87
78
|
this.camera.movement.activeInput = false;
|
|
88
79
|
super.onButtonUp(_evt);
|
|
89
80
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geospatialCameraPointersInput.js","sourceRoot":"","sources":["../../../../../dev/core/src/Cameras/Inputs/geospatialCameraPointersInput.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"geospatialCameraPointersInput.js","sourceRoot":"","sources":["../../../../../dev/core/src/Cameras/Inputs/geospatialCameraPointersInput.ts"],"names":[],"mappings":"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","sourcesContent":["import type { GeospatialCamera } from \"../../Cameras/geospatialCamera\";\r\nimport type { IPointerEvent } from \"../../Events/deviceInputEvents\";\r\nimport type { PointerTouch } from \"../../Events/pointerEvents\";\r\nimport type { Nullable } from \"../../types\";\r\nimport { OrbitCameraPointersInput } from \"./orbitCameraPointersInput\";\r\n\r\n/**\r\n * @experimental\r\n * Geospatial camera inputs can simulate dragging the globe around or tilting the camera around some point on the globe\r\n * This class will update the GeospatialCameraMovement class's movementDeltaCurrentFrame, and the camera is responsible for using these updates to calculate viewMatrix appropriately\r\n *\r\n * As of right now, the camera correction logic (to keep the camera geospatially oriented around the globe) is happening within the camera class when calculating viewmatrix\r\n * As this is experimental, it is possible we move that correction step to live within the input class (to enable non-corrected translations in the future), say if we want to allow the camera to move outside of the globe's orbit\r\n *\r\n * Left mouse button: drag globe\r\n * Middle mouse button: tilt globe\r\n * Right mouse button: tilt globe\r\n *\r\n */\r\nexport class GeospatialCameraPointersInput extends OrbitCameraPointersInput {\r\n public camera: GeospatialCamera;\r\n\r\n public override getClassName(): string {\r\n return \"GeospatialCameraPointersInput\";\r\n }\r\n\r\n public override onButtonDown(evt: IPointerEvent): void {\r\n this.camera.movement.activeInput = true;\r\n const scene = this.camera.getScene();\r\n switch (evt.button) {\r\n case 0: // Left button - drag/pan globe under cursor\r\n this.camera.movement.startDrag(scene.pointerX, scene.pointerY);\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n public override onTouch(point: Nullable<PointerTouch>, offsetX: number, offsetY: number): void {\r\n // Single finger touch (no button property) or left button (button 0) = drag\r\n const button = point?.button ?? 0; // Default to button 0 (drag) if undefined\r\n const scene = this.camera.getScene();\r\n switch (button) {\r\n case 0: // Left button / single touch - drag/pan globe under cursor\r\n this.camera.movement.handleDrag(scene.pointerX, scene.pointerY);\r\n break;\r\n case 1: // Middle button - tilt camera\r\n case 2: // Right button - tilt camera\r\n this._handleTilt(offsetX, offsetY);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Move camera from multitouch (pinch) zoom distances.\r\n * @param previousPinchSquaredDistance\r\n * @param pinchSquaredDistance\r\n */\r\n protected override _computePinchZoom(previousPinchSquaredDistance: number, pinchSquaredDistance: number): void {\r\n this.camera.radius = (this.camera.radius * Math.sqrt(previousPinchSquaredDistance)) / Math.sqrt(pinchSquaredDistance);\r\n }\r\n\r\n /**\r\n * Move camera from multi touch panning positions.\r\n * In geospatialcamera, multi touch panning tilts the globe (whereas single touch will pan/drag it)\r\n * @param previousMultiTouchPanPosition\r\n * @param multiTouchPanPosition\r\n */\r\n protected override _computeMultiTouchPanning(previousMultiTouchPanPosition: Nullable<PointerTouch>, multiTouchPanPosition: Nullable<PointerTouch>): void {\r\n if (previousMultiTouchPanPosition && multiTouchPanPosition) {\r\n const moveDeltaX = multiTouchPanPosition.x - previousMultiTouchPanPosition.x;\r\n const moveDeltaY = multiTouchPanPosition.y - previousMultiTouchPanPosition.y;\r\n this._handleTilt(moveDeltaX, moveDeltaY);\r\n }\r\n }\r\n\r\n public override onDoubleTap(type: string): void {\r\n const pickResult = this.camera._scene.pick(this.camera._scene.pointerX, this.camera._scene.pointerY, this.camera.pickPredicate);\r\n if (pickResult.pickedPoint) {\r\n void this.camera.flyToPointAsync(pickResult.pickedPoint);\r\n }\r\n }\r\n\r\n public override onMultiTouch(\r\n pointA: Nullable<PointerTouch>,\r\n pointB: Nullable<PointerTouch>,\r\n previousPinchSquaredDistance: number,\r\n pinchSquaredDistance: number,\r\n previousMultiTouchPanPosition: Nullable<PointerTouch>,\r\n multiTouchPanPosition: Nullable<PointerTouch>\r\n ): void {\r\n this._shouldStartPinchZoom =\r\n this._twoFingerActivityCount < 20 && Math.abs(Math.sqrt(pinchSquaredDistance) - Math.sqrt(previousPinchSquaredDistance)) > this.camera.limits.pinchToPanMax;\r\n super.onMultiTouch(pointA, pointB, previousPinchSquaredDistance, pinchSquaredDistance, previousMultiTouchPanPosition, multiTouchPanPosition);\r\n }\r\n\r\n public override onButtonUp(_evt: IPointerEvent): void {\r\n this.camera.movement.stopDrag();\r\n this.camera.movement.activeInput = false;\r\n super.onButtonUp(_evt);\r\n }\r\n\r\n private _handleTilt(deltaX: number, deltaY: number): void {\r\n this.camera.movement.rotationAccumulatedPixels.y -= deltaX; // yaw - looking side to side\r\n this.camera.movement.rotationAccumulatedPixels.x -= deltaY; // pitch - look up towards sky / down towards ground\r\n }\r\n}\r\n"]}
|
|
@@ -84,19 +84,19 @@ export declare class CameraMovement {
|
|
|
84
84
|
*/
|
|
85
85
|
/**
|
|
86
86
|
* Accumulated pixel delta (by input classes) for zoom this frame
|
|
87
|
-
* Read by computeCurrentFrameDeltas() function and converted into
|
|
87
|
+
* Read by computeCurrentFrameDeltas() function and converted into zoomDeltaCurrentFrame (taking speed into account)
|
|
88
88
|
* Reset to zero after each frame
|
|
89
89
|
*/
|
|
90
90
|
zoomAccumulatedPixels: number;
|
|
91
91
|
/**
|
|
92
92
|
* Accumulated pixel delta (by input classes) for panning this frame
|
|
93
|
-
* Read by computeCurrentFrameDeltas() function and converted into
|
|
93
|
+
* Read by computeCurrentFrameDeltas() function and converted into panDeltaCurrentFrame (taking speed into account)
|
|
94
94
|
* Reset to zero after each frame
|
|
95
95
|
*/
|
|
96
96
|
panAccumulatedPixels: Vector3;
|
|
97
97
|
/**
|
|
98
98
|
* Accumulated pixel delta (by input classes) for rotation this frame
|
|
99
|
-
* Read by computeCurrentFrameDeltas() function and converted into
|
|
99
|
+
* Read by computeCurrentFrameDeltas() function and converted into rotationDeltaCurrentFrame (taking speed into account)
|
|
100
100
|
* Reset to zero after each frame
|
|
101
101
|
*/
|
|
102
102
|
rotationAccumulatedPixels: Vector3;
|
|
@@ -123,7 +123,7 @@ export declare class CameraMovement {
|
|
|
123
123
|
* -----------------------------------
|
|
124
124
|
*/
|
|
125
125
|
/**
|
|
126
|
-
* Zoom velocity used for inertia calculations (
|
|
126
|
+
* Zoom pixel velocity used for inertia calculations (pixels / ms).
|
|
127
127
|
*/
|
|
128
128
|
protected _zoomVelocity: number;
|
|
129
129
|
/**
|
|
@@ -84,19 +84,19 @@ export class CameraMovement {
|
|
|
84
84
|
*/
|
|
85
85
|
/**
|
|
86
86
|
* Accumulated pixel delta (by input classes) for zoom this frame
|
|
87
|
-
* Read by computeCurrentFrameDeltas() function and converted into
|
|
87
|
+
* Read by computeCurrentFrameDeltas() function and converted into zoomDeltaCurrentFrame (taking speed into account)
|
|
88
88
|
* Reset to zero after each frame
|
|
89
89
|
*/
|
|
90
90
|
this.zoomAccumulatedPixels = 0;
|
|
91
91
|
/**
|
|
92
92
|
* Accumulated pixel delta (by input classes) for panning this frame
|
|
93
|
-
* Read by computeCurrentFrameDeltas() function and converted into
|
|
93
|
+
* Read by computeCurrentFrameDeltas() function and converted into panDeltaCurrentFrame (taking speed into account)
|
|
94
94
|
* Reset to zero after each frame
|
|
95
95
|
*/
|
|
96
96
|
this.panAccumulatedPixels = new Vector3();
|
|
97
97
|
/**
|
|
98
98
|
* Accumulated pixel delta (by input classes) for rotation this frame
|
|
99
|
-
* Read by computeCurrentFrameDeltas() function and converted into
|
|
99
|
+
* Read by computeCurrentFrameDeltas() function and converted into rotationDeltaCurrentFrame (taking speed into account)
|
|
100
100
|
* Reset to zero after each frame
|
|
101
101
|
*/
|
|
102
102
|
this.rotationAccumulatedPixels = new Vector3();
|
|
@@ -123,7 +123,7 @@ export class CameraMovement {
|
|
|
123
123
|
* -----------------------------------
|
|
124
124
|
*/
|
|
125
125
|
/**
|
|
126
|
-
* Zoom velocity used for inertia calculations (
|
|
126
|
+
* Zoom pixel velocity used for inertia calculations (pixels / ms).
|
|
127
127
|
*/
|
|
128
128
|
this._zoomVelocity = 0;
|
|
129
129
|
/**
|
|
@@ -154,12 +154,12 @@ export class CameraMovement {
|
|
|
154
154
|
if (hasUserInput && this._behavior?.isInterpolating) {
|
|
155
155
|
this._behavior.stopAllAnimations();
|
|
156
156
|
}
|
|
157
|
-
this._panVelocity.copyFromFloats(this._calculateCurrentVelocity(this._panVelocity.x, this.panAccumulatedPixels.x, this.
|
|
158
|
-
this._panVelocity.scaleToRef(deltaTimeMs, this.panDeltaCurrentFrame);
|
|
159
|
-
this._rotationVelocity.copyFromFloats(this._calculateCurrentVelocity(this._rotationVelocity.x, this.rotationAccumulatedPixels.x, this.
|
|
160
|
-
this._rotationVelocity.
|
|
161
|
-
this._zoomVelocity = this._calculateCurrentVelocity(this._zoomVelocity, this.zoomAccumulatedPixels, this.
|
|
162
|
-
this.zoomDeltaCurrentFrame = this._zoomVelocity * deltaTimeMs;
|
|
157
|
+
this._panVelocity.copyFromFloats(this._calculateCurrentVelocity(this._panVelocity.x, this.panAccumulatedPixels.x, this.panInertia), this._calculateCurrentVelocity(this._panVelocity.y, this.panAccumulatedPixels.y, this.panInertia), this._calculateCurrentVelocity(this._panVelocity.z, this.panAccumulatedPixels.z, this.panInertia));
|
|
158
|
+
this._panVelocity.scaleToRef(this.panSpeed * this._panSpeedMultiplier * deltaTimeMs, this.panDeltaCurrentFrame);
|
|
159
|
+
this._rotationVelocity.copyFromFloats(this._calculateCurrentVelocity(this._rotationVelocity.x, this.rotationAccumulatedPixels.x, this.rotationInertia), this._calculateCurrentVelocity(this._rotationVelocity.y, this.rotationAccumulatedPixels.y, this.rotationInertia), this._calculateCurrentVelocity(this._rotationVelocity.z, this.rotationAccumulatedPixels.z, this.rotationInertia));
|
|
160
|
+
this.rotationDeltaCurrentFrame.copyFromFloats(this._rotationVelocity.x * this.rotationXSpeed * deltaTimeMs, this._rotationVelocity.y * this.rotationYSpeed * deltaTimeMs, this._rotationVelocity.z * this.rotationYSpeed * deltaTimeMs);
|
|
161
|
+
this._zoomVelocity = this._calculateCurrentVelocity(this._zoomVelocity, this.zoomAccumulatedPixels, this.zoomInertia);
|
|
162
|
+
this.zoomDeltaCurrentFrame = this._zoomVelocity * (this.zoomSpeed * this._zoomSpeedMultiplier) * deltaTimeMs;
|
|
163
163
|
this._prevFrameTimeMs = deltaTimeMs;
|
|
164
164
|
this.zoomAccumulatedPixels = 0;
|
|
165
165
|
this.panAccumulatedPixels.setAll(0);
|
|
@@ -168,13 +168,12 @@ export class CameraMovement {
|
|
|
168
168
|
get isInterpolating() {
|
|
169
169
|
return !!this._behavior?.isInterpolating;
|
|
170
170
|
}
|
|
171
|
-
_calculateCurrentVelocity(velocityRef, pixelDelta,
|
|
171
|
+
_calculateCurrentVelocity(velocityRef, pixelDelta, inertialDecayFactor) {
|
|
172
172
|
let inputVelocity = velocityRef;
|
|
173
173
|
const deltaTimeMs = this._scene.getEngine().getDeltaTime();
|
|
174
|
-
// If we are actively
|
|
174
|
+
// If we are actively receiving input or have accumulated some pixel delta since last frame, calculate inputVelocity (inertia doesn't kick in yet)
|
|
175
175
|
if (pixelDelta !== 0 || this.activeInput) {
|
|
176
|
-
|
|
177
|
-
inputVelocity = pixelsPerMs * speedFactor;
|
|
176
|
+
inputVelocity = pixelDelta / deltaTimeMs;
|
|
178
177
|
}
|
|
179
178
|
else if (!this.activeInput && inputVelocity !== 0) {
|
|
180
179
|
// If we are not receiving input and velocity isn't already zero, apply inertial decay to decelerate velocity
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cameraMovement.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/cameraMovement.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAGlD,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAE,CAAC;AACvC;;;;;;GAMG;AACH,MAAM,OAAO,cAAc;IAyIvB,YACI,KAAY,EACF,eAAwB,EACxB,SAAiC;QADjC,oBAAe,GAAf,eAAe,CAAS;QACxB,cAAS,GAAT,SAAS,CAAwB;QAzI/C;;;WAGG;QACI,gBAAW,GAAY,KAAK,CAAC;QAEpC;;;;WAIG;QACH;;WAEG;QACI,cAAS,GAAW,CAAC,CAAC;QAC7B;;WAEG;QACI,aAAQ,GAAW,CAAC,CAAC;QAC5B;;WAEG;QACI,mBAAc,GAAW,CAAC,CAAC;QAClC;;WAEG;QACI,mBAAc,GAAW,CAAC,CAAC;QAElC;;;;;WAKG;QACH;;WAEG;QACO,yBAAoB,GAAW,CAAC,CAAC;QAC3C;;WAEG;QACO,wBAAmB,GAAW,CAAC,CAAC;QAE1C;;;;;;;;;WASG;QACH;;;WAGG;QACI,gBAAW,GAAW,GAAG,CAAC;QACjC;;;WAGG;QACI,eAAU,GAAW,GAAG,CAAC;QAChC;;;WAGG;QACI,oBAAe,GAAW,GAAG,CAAC;QAErC;;;;WAIG;QACH;;;;WAIG;QACI,0BAAqB,GAAW,CAAC,CAAC;QACzC;;;;WAIG;QACI,yBAAoB,GAAY,IAAI,OAAO,EAAE,CAAC;QACrD;;;;WAIG;QACI,8BAAyB,GAAY,IAAI,OAAO,EAAE,CAAC;QAE1D;;;;WAIG;QACH;;WAEG;QACI,0BAAqB,GAAW,CAAC,CAAC;QACzC;;WAEG;QACI,yBAAoB,GAAY,OAAO,CAAC,IAAI,EAAE,CAAC;QACtD;;WAEG;QACI,8BAAyB,GAAY,OAAO,CAAC,IAAI,EAAE,CAAC;QAE3D;;;;WAIG;QACH;;WAEG;QACO,kBAAa,GAAW,CAAC,CAAC;QACpC;;WAEG;QACK,iBAAY,GAAY,IAAI,OAAO,EAAE,CAAC;QAC9C;;WAEG;QACK,sBAAiB,GAAY,IAAI,OAAO,EAAE,CAAC;QAEnD;;WAEG;QACK,qBAAgB,GAAW,oBAAoB,CAAC;QAOpD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACI,yBAAyB;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,YAAY,EAAE,CAAC;QAE3D,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACzC,IAAI,CAAC,qBAAqB,GAAG,CAAC,CAAC;QAE/B,MAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,CAAC,aAAa,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,yBAAyB,CAAC,aAAa,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,qBAAqB,KAAK,CAAC,CAAC;QAE7J,IAAI,YAAY,IAAI,IAAI,CAAC,SAAS,EAAE,eAAe,EAAE,CAAC;YAClD,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC;QACvC,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,cAAc,CAC5B,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,UAAU,CAAC,EAC3I,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,UAAU,CAAC,EAC3I,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,UAAU,CAAC,CAC9I,CAAC;QACF,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAErE,IAAI,CAAC,iBAAiB,CAAC,cAAc,CACjC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,yBAAyB,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,EACrI,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,yBAAyB,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,EACrI,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,yBAAyB,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,CACxI,CAAC;QACF,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,yBAAyB,CAAC,CAAC;QAE/E,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,qBAAqB,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAClK,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,aAAa,GAAG,WAAW,CAAC;QAE9D,IAAI,CAAC,gBAAgB,GAAG,WAAW,CAAC;QACpC,IAAI,CAAC,qBAAqB,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,IAAW,eAAe;QACtB,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC;IAC7C,CAAC;IAEO,yBAAyB,CAAC,WAAmB,EAAE,UAAkB,EAAE,WAAmB,EAAE,mBAA2B;QACvH,IAAI,aAAa,GAAG,WAAW,CAAC;QAChC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,YAAY,EAAE,CAAC;QAE3D,iJAAiJ;QACjJ,IAAI,UAAU,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,UAAU,GAAG,WAAW,CAAC;YAC7C,aAAa,GAAG,WAAW,GAAG,WAAW,CAAC;QAC9C,CAAC;aAAM,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;YAClD,6GAA6G;YAC7G,MAAM,qBAAqB,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,gBAAgB,GAAG,oBAAoB,CAAC,CAAC;YAC1G,aAAa,IAAI,qBAAqB,CAAC;YACvC,IAAI,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,OAAO,EAAE,CAAC;gBACrC,aAAa,GAAG,CAAC,CAAC;YACtB,CAAC;QACL,CAAC;QAED,OAAO,aAAa,CAAC;IACzB,CAAC;CACJ","sourcesContent":["import type { Scene } from \"../scene\";\r\nimport { Vector3 } from \"../Maths/math.vector\";\r\nimport { Epsilon } from \"../Maths/math.constants\";\r\nimport type { InterpolatingBehavior } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\n\r\nconst FrameDurationAt60FPS = 1000 / 60;\r\n/**\r\n * @experimental\r\n * This class is subject to change as geospatial camera evolves.\r\n *\r\n * It is intended to hold all logic related to converting input pixel deltas into current frame deltas, taking speed / framerate into account\r\n * to ensure smooth frame-rate-independent movement\r\n */\r\nexport class CameraMovement {\r\n protected _scene: Scene;\r\n\r\n /**\r\n * Should be set by input classes to indicates whether there is active input this frame\r\n * This helps us differentiate between 0 pixel delta due to no input vs user actively holding still\r\n */\r\n public activeInput: boolean = false;\r\n\r\n /**\r\n * ------------ Speed ----------------\r\n * Speed defines the amount of camera movement expected per input pixel movement\r\n * -----------------------------------\r\n */\r\n /**\r\n * Desired coordinate unit movement per input pixel when zooming\r\n */\r\n public zoomSpeed: number = 1;\r\n /**\r\n * Desired coordinate unit movement per input pixel when panning\r\n */\r\n public panSpeed: number = 1;\r\n /**\r\n * Desired radians movement per input pixel when rotating along x axis\r\n */\r\n public rotationXSpeed: number = 1;\r\n /**\r\n * Desired radians movement per input pixel when rotating along y axis\r\n */\r\n public rotationYSpeed: number = 1;\r\n\r\n /**\r\n * ----------- Speed multipliers ---------------\r\n * Multipliers allow movement classes to modify the effective speed dynamically per-frame\r\n * (ex: scale zoom based on distance from target)\r\n * -----------------------------------\r\n */\r\n /**\r\n * Multiplied atop zoom speed. Used to dynamically adjust zoom speed based on per-frame context (ex: zoom faster when further from target)\r\n */\r\n protected _zoomSpeedMultiplier: number = 1;\r\n /**\r\n * Multiplied atop pan speed. Used to dynamically adjust pan speed based on per-frame context (ex: pan slowly when close to target)\r\n */\r\n protected _panSpeedMultiplier: number = 1;\r\n\r\n /**\r\n * ---------- Inertia ----------------\r\n * Inertia represents the decay factor per-frame applied to the velocity when there is no user input.\r\n * 0 = No inertia, instant stop (velocity immediately becomes 0)\r\n * 0.5 = Strong decay, velocity halves every frame at 60fps\r\n * 0.9 = Moderate inertia, velocity retains 90% per frame at 60fps\r\n * 0.95 = High inertia, smooth glide, velocity retains 95% per frame at 60fps\r\n * 1 = Infinite inertia, never stops (velocity never decays)\r\n * -----------------------------------\r\n */\r\n /**\r\n * Inertia applied to the zoom velocity when there is no user input.\r\n * Higher inertia === slower decay, velocity retains more of its value each frame\r\n */\r\n public zoomInertia: number = 0.9;\r\n /**\r\n * Inertia applied to the panning velocity when there is no user input.\r\n * Higher inertia === slower decay, velocity retains more of its value each frame\r\n */\r\n public panInertia: number = 0.9;\r\n /**\r\n * Inertia applied to the rotation velocity when there is no user input.\r\n * Higher inertia === slower decay, velocity retains more of its value each frame\r\n */\r\n public rotationInertia: number = 0.9;\r\n\r\n /**\r\n * ---------- Accumulated Pixel Deltas -----------\r\n * Pixel inputs accumulated throughout the frame by input classes (reset each frame after processing)\r\n * -----------------------------------\r\n */\r\n /**\r\n * Accumulated pixel delta (by input classes) for zoom this frame\r\n * Read by computeCurrentFrameDeltas() function and converted into currentFrameTranslationDelta (taking speed into account)\r\n * Reset to zero after each frame\r\n */\r\n public zoomAccumulatedPixels: number = 0;\r\n /**\r\n * Accumulated pixel delta (by input classes) for panning this frame\r\n * Read by computeCurrentFrameDeltas() function and converted into currentFrameTranslationDelta (taking speed into account)\r\n * Reset to zero after each frame\r\n */\r\n public panAccumulatedPixels: Vector3 = new Vector3();\r\n /**\r\n * Accumulated pixel delta (by input classes) for rotation this frame\r\n * Read by computeCurrentFrameDeltas() function and converted into currentFrameTranslationDelta (taking speed into account)\r\n * Reset to zero after each frame\r\n */\r\n public rotationAccumulatedPixels: Vector3 = new Vector3();\r\n\r\n /**\r\n * ---------- Current Frame Movement Deltas -----------\r\n * Deltas read on each frame by camera class in order to move the camera\r\n * -----------------------------------\r\n */\r\n /**\r\n * Zoom delta to apply to camera this frame, computed by computeCurrentFrameDeltas() from zoomPixelDelta (taking speed into account)\r\n */\r\n public zoomDeltaCurrentFrame: number = 0;\r\n /**\r\n * Pan delta to apply to camera this frame, computed by computeCurrentFrameDeltas() from panPixelDelta (taking speed into account)\r\n */\r\n public panDeltaCurrentFrame: Vector3 = Vector3.Zero();\r\n /**\r\n * Rotation delta to apply to camera this frame, computed by computeCurrentFrameDeltas() from rotationPixelDelta (taking speed into account)\r\n */\r\n public rotationDeltaCurrentFrame: Vector3 = Vector3.Zero();\r\n\r\n /**\r\n * ---------- Velocity -----------\r\n * Used to track velocity between frames for inertia calculation\r\n * -----------------------------------\r\n */\r\n /**\r\n * Zoom velocity used for inertia calculations (movement / time)\r\n */\r\n protected _zoomVelocity: number = 0;\r\n /**\r\n * Pan velocity used for inertia calculations (movement / time)\r\n */\r\n private _panVelocity: Vector3 = new Vector3();\r\n /**\r\n * Rotation velocity used for inertia calculations (movement / time)\r\n */\r\n private _rotationVelocity: Vector3 = new Vector3();\r\n\r\n /**\r\n * Used when calculating inertial decay. Default to 60fps\r\n */\r\n private _prevFrameTimeMs: number = FrameDurationAt60FPS;\r\n\r\n constructor(\r\n scene: Scene,\r\n protected _cameraPosition: Vector3,\r\n protected _behavior?: InterpolatingBehavior\r\n ) {\r\n this._scene = scene;\r\n }\r\n\r\n /**\r\n * When called, will take the accumulated pixel deltas set by input classes and convert them into current frame deltas, stored in currentFrameMovementDelta properties\r\n * Takes speed, scaling, inertia, and framerate into account to ensure smooth movement\r\n * Zeros out pixelDeltas before returning\r\n */\r\n public computeCurrentFrameDeltas(): void {\r\n const deltaTimeMs = this._scene.getEngine().getDeltaTime();\r\n\r\n this.panDeltaCurrentFrame.setAll(0);\r\n this.rotationDeltaCurrentFrame.setAll(0);\r\n this.zoomDeltaCurrentFrame = 0;\r\n\r\n const hasUserInput = this.panAccumulatedPixels.lengthSquared() > 0 || this.rotationAccumulatedPixels.lengthSquared() > 0 || this.zoomAccumulatedPixels !== 0;\r\n\r\n if (hasUserInput && this._behavior?.isInterpolating) {\r\n this._behavior.stopAllAnimations();\r\n }\r\n\r\n this._panVelocity.copyFromFloats(\r\n this._calculateCurrentVelocity(this._panVelocity.x, this.panAccumulatedPixels.x, this.panSpeed * this._panSpeedMultiplier, this.panInertia),\r\n this._calculateCurrentVelocity(this._panVelocity.y, this.panAccumulatedPixels.y, this.panSpeed * this._panSpeedMultiplier, this.panInertia),\r\n this._calculateCurrentVelocity(this._panVelocity.z, this.panAccumulatedPixels.z, this.panSpeed * this._panSpeedMultiplier, this.panInertia)\r\n );\r\n this._panVelocity.scaleToRef(deltaTimeMs, this.panDeltaCurrentFrame);\r\n\r\n this._rotationVelocity.copyFromFloats(\r\n this._calculateCurrentVelocity(this._rotationVelocity.x, this.rotationAccumulatedPixels.x, this.rotationXSpeed, this.rotationInertia),\r\n this._calculateCurrentVelocity(this._rotationVelocity.y, this.rotationAccumulatedPixels.y, this.rotationYSpeed, this.rotationInertia),\r\n this._calculateCurrentVelocity(this._rotationVelocity.z, this.rotationAccumulatedPixels.z, this.rotationYSpeed, this.rotationInertia)\r\n );\r\n this._rotationVelocity.scaleToRef(deltaTimeMs, this.rotationDeltaCurrentFrame);\r\n\r\n this._zoomVelocity = this._calculateCurrentVelocity(this._zoomVelocity, this.zoomAccumulatedPixels, this.zoomSpeed * this._zoomSpeedMultiplier, this.zoomInertia);\r\n this.zoomDeltaCurrentFrame = this._zoomVelocity * deltaTimeMs;\r\n\r\n this._prevFrameTimeMs = deltaTimeMs;\r\n this.zoomAccumulatedPixels = 0;\r\n this.panAccumulatedPixels.setAll(0);\r\n this.rotationAccumulatedPixels.setAll(0);\r\n }\r\n\r\n public get isInterpolating(): boolean {\r\n return !!this._behavior?.isInterpolating;\r\n }\r\n\r\n private _calculateCurrentVelocity(velocityRef: number, pixelDelta: number, speedFactor: number, inertialDecayFactor: number): number {\r\n let inputVelocity = velocityRef;\r\n const deltaTimeMs = this._scene.getEngine().getDeltaTime();\r\n\r\n // If we are actively recieving input or have accumulated some pixel delta since last frame, calculate inputVelocity (inertia doesn't kickin yet)\r\n if (pixelDelta !== 0 || this.activeInput) {\r\n const pixelsPerMs = pixelDelta / deltaTimeMs;\r\n inputVelocity = pixelsPerMs * speedFactor;\r\n } else if (!this.activeInput && inputVelocity !== 0) {\r\n // If we are not receiving input and velocity isn't already zero, apply inertial decay to decelerate velocity\r\n const frameIndependentDecay = Math.pow(inertialDecayFactor, this._prevFrameTimeMs / FrameDurationAt60FPS);\r\n inputVelocity *= frameIndependentDecay;\r\n if (Math.abs(inputVelocity) <= Epsilon) {\r\n inputVelocity = 0;\r\n }\r\n }\r\n\r\n return inputVelocity;\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"cameraMovement.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/cameraMovement.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Scene } from \"../scene\";\r\nimport { Vector3 } from \"../Maths/math.vector\";\r\nimport { Epsilon } from \"../Maths/math.constants\";\r\nimport type { InterpolatingBehavior } from \"../Behaviors/Cameras/interpolatingBehavior\";\r\n\r\nconst FrameDurationAt60FPS = 1000 / 60;\r\n/**\r\n * @experimental\r\n * This class is subject to change as geospatial camera evolves.\r\n *\r\n * It is intended to hold all logic related to converting input pixel deltas into current frame deltas, taking speed / framerate into account\r\n * to ensure smooth frame-rate-independent movement\r\n */\r\nexport class CameraMovement {\r\n protected _scene: Scene;\r\n\r\n /**\r\n * Should be set by input classes to indicates whether there is active input this frame\r\n * This helps us differentiate between 0 pixel delta due to no input vs user actively holding still\r\n */\r\n public activeInput: boolean = false;\r\n\r\n /**\r\n * ------------ Speed ----------------\r\n * Speed defines the amount of camera movement expected per input pixel movement\r\n * -----------------------------------\r\n */\r\n /**\r\n * Desired coordinate unit movement per input pixel when zooming\r\n */\r\n public zoomSpeed: number = 1;\r\n /**\r\n * Desired coordinate unit movement per input pixel when panning\r\n */\r\n public panSpeed: number = 1;\r\n /**\r\n * Desired radians movement per input pixel when rotating along x axis\r\n */\r\n public rotationXSpeed: number = 1;\r\n /**\r\n * Desired radians movement per input pixel when rotating along y axis\r\n */\r\n public rotationYSpeed: number = 1;\r\n\r\n /**\r\n * ----------- Speed multipliers ---------------\r\n * Multipliers allow movement classes to modify the effective speed dynamically per-frame\r\n * (ex: scale zoom based on distance from target)\r\n * -----------------------------------\r\n */\r\n /**\r\n * Multiplied atop zoom speed. Used to dynamically adjust zoom speed based on per-frame context (ex: zoom faster when further from target)\r\n */\r\n protected _zoomSpeedMultiplier: number = 1;\r\n /**\r\n * Multiplied atop pan speed. Used to dynamically adjust pan speed based on per-frame context (ex: pan slowly when close to target)\r\n */\r\n protected _panSpeedMultiplier: number = 1;\r\n\r\n /**\r\n * ---------- Inertia ----------------\r\n * Inertia represents the decay factor per-frame applied to the velocity when there is no user input.\r\n * 0 = No inertia, instant stop (velocity immediately becomes 0)\r\n * 0.5 = Strong decay, velocity halves every frame at 60fps\r\n * 0.9 = Moderate inertia, velocity retains 90% per frame at 60fps\r\n * 0.95 = High inertia, smooth glide, velocity retains 95% per frame at 60fps\r\n * 1 = Infinite inertia, never stops (velocity never decays)\r\n * -----------------------------------\r\n */\r\n /**\r\n * Inertia applied to the zoom velocity when there is no user input.\r\n * Higher inertia === slower decay, velocity retains more of its value each frame\r\n */\r\n public zoomInertia: number = 0.9;\r\n /**\r\n * Inertia applied to the panning velocity when there is no user input.\r\n * Higher inertia === slower decay, velocity retains more of its value each frame\r\n */\r\n public panInertia: number = 0.9;\r\n /**\r\n * Inertia applied to the rotation velocity when there is no user input.\r\n * Higher inertia === slower decay, velocity retains more of its value each frame\r\n */\r\n public rotationInertia: number = 0.9;\r\n\r\n /**\r\n * ---------- Accumulated Pixel Deltas -----------\r\n * Pixel inputs accumulated throughout the frame by input classes (reset each frame after processing)\r\n * -----------------------------------\r\n */\r\n /**\r\n * Accumulated pixel delta (by input classes) for zoom this frame\r\n * Read by computeCurrentFrameDeltas() function and converted into zoomDeltaCurrentFrame (taking speed into account)\r\n * Reset to zero after each frame\r\n */\r\n public zoomAccumulatedPixels: number = 0;\r\n /**\r\n * Accumulated pixel delta (by input classes) for panning this frame\r\n * Read by computeCurrentFrameDeltas() function and converted into panDeltaCurrentFrame (taking speed into account)\r\n * Reset to zero after each frame\r\n */\r\n public panAccumulatedPixels: Vector3 = new Vector3();\r\n /**\r\n * Accumulated pixel delta (by input classes) for rotation this frame\r\n * Read by computeCurrentFrameDeltas() function and converted into rotationDeltaCurrentFrame (taking speed into account)\r\n * Reset to zero after each frame\r\n */\r\n public rotationAccumulatedPixels: Vector3 = new Vector3();\r\n\r\n /**\r\n * ---------- Current Frame Movement Deltas -----------\r\n * Deltas read on each frame by camera class in order to move the camera\r\n * -----------------------------------\r\n */\r\n /**\r\n * Zoom delta to apply to camera this frame, computed by computeCurrentFrameDeltas() from zoomPixelDelta (taking speed into account)\r\n */\r\n public zoomDeltaCurrentFrame: number = 0;\r\n /**\r\n * Pan delta to apply to camera this frame, computed by computeCurrentFrameDeltas() from panPixelDelta (taking speed into account)\r\n */\r\n public panDeltaCurrentFrame: Vector3 = Vector3.Zero();\r\n /**\r\n * Rotation delta to apply to camera this frame, computed by computeCurrentFrameDeltas() from rotationPixelDelta (taking speed into account)\r\n */\r\n public rotationDeltaCurrentFrame: Vector3 = Vector3.Zero();\r\n\r\n /**\r\n * ---------- Velocity -----------\r\n * Used to track velocity between frames for inertia calculation\r\n * -----------------------------------\r\n */\r\n /**\r\n * Zoom pixel velocity used for inertia calculations (pixels / ms).\r\n */\r\n protected _zoomVelocity: number = 0;\r\n /**\r\n * Pan velocity used for inertia calculations (movement / time)\r\n */\r\n private _panVelocity: Vector3 = new Vector3();\r\n /**\r\n * Rotation velocity used for inertia calculations (movement / time)\r\n */\r\n private _rotationVelocity: Vector3 = new Vector3();\r\n\r\n /**\r\n * Used when calculating inertial decay. Default to 60fps\r\n */\r\n private _prevFrameTimeMs: number = FrameDurationAt60FPS;\r\n\r\n constructor(\r\n scene: Scene,\r\n protected _cameraPosition: Vector3,\r\n protected _behavior?: InterpolatingBehavior\r\n ) {\r\n this._scene = scene;\r\n }\r\n\r\n /**\r\n * When called, will take the accumulated pixel deltas set by input classes and convert them into current frame deltas, stored in currentFrameMovementDelta properties\r\n * Takes speed, scaling, inertia, and framerate into account to ensure smooth movement\r\n * Zeros out pixelDeltas before returning\r\n */\r\n public computeCurrentFrameDeltas(): void {\r\n const deltaTimeMs = this._scene.getEngine().getDeltaTime();\r\n\r\n this.panDeltaCurrentFrame.setAll(0);\r\n this.rotationDeltaCurrentFrame.setAll(0);\r\n this.zoomDeltaCurrentFrame = 0;\r\n\r\n const hasUserInput = this.panAccumulatedPixels.lengthSquared() > 0 || this.rotationAccumulatedPixels.lengthSquared() > 0 || this.zoomAccumulatedPixels !== 0;\r\n\r\n if (hasUserInput && this._behavior?.isInterpolating) {\r\n this._behavior.stopAllAnimations();\r\n }\r\n\r\n this._panVelocity.copyFromFloats(\r\n this._calculateCurrentVelocity(this._panVelocity.x, this.panAccumulatedPixels.x, this.panInertia),\r\n this._calculateCurrentVelocity(this._panVelocity.y, this.panAccumulatedPixels.y, this.panInertia),\r\n this._calculateCurrentVelocity(this._panVelocity.z, this.panAccumulatedPixels.z, this.panInertia)\r\n );\r\n this._panVelocity.scaleToRef(this.panSpeed * this._panSpeedMultiplier * deltaTimeMs, this.panDeltaCurrentFrame);\r\n\r\n this._rotationVelocity.copyFromFloats(\r\n this._calculateCurrentVelocity(this._rotationVelocity.x, this.rotationAccumulatedPixels.x, this.rotationInertia),\r\n this._calculateCurrentVelocity(this._rotationVelocity.y, this.rotationAccumulatedPixels.y, this.rotationInertia),\r\n this._calculateCurrentVelocity(this._rotationVelocity.z, this.rotationAccumulatedPixels.z, this.rotationInertia)\r\n );\r\n this.rotationDeltaCurrentFrame.copyFromFloats(\r\n this._rotationVelocity.x * this.rotationXSpeed * deltaTimeMs,\r\n this._rotationVelocity.y * this.rotationYSpeed * deltaTimeMs,\r\n this._rotationVelocity.z * this.rotationYSpeed * deltaTimeMs\r\n );\r\n\r\n this._zoomVelocity = this._calculateCurrentVelocity(this._zoomVelocity, this.zoomAccumulatedPixels, this.zoomInertia);\r\n this.zoomDeltaCurrentFrame = this._zoomVelocity * (this.zoomSpeed * this._zoomSpeedMultiplier) * deltaTimeMs;\r\n\r\n this._prevFrameTimeMs = deltaTimeMs;\r\n this.zoomAccumulatedPixels = 0;\r\n this.panAccumulatedPixels.setAll(0);\r\n this.rotationAccumulatedPixels.setAll(0);\r\n }\r\n\r\n public get isInterpolating(): boolean {\r\n return !!this._behavior?.isInterpolating;\r\n }\r\n\r\n private _calculateCurrentVelocity(velocityRef: number, pixelDelta: number, inertialDecayFactor: number): number {\r\n let inputVelocity = velocityRef;\r\n const deltaTimeMs = this._scene.getEngine().getDeltaTime();\r\n\r\n // If we are actively receiving input or have accumulated some pixel delta since last frame, calculate inputVelocity (inertia doesn't kick in yet)\r\n if (pixelDelta !== 0 || this.activeInput) {\r\n inputVelocity = pixelDelta / deltaTimeMs;\r\n } else if (!this.activeInput && inputVelocity !== 0) {\r\n // If we are not receiving input and velocity isn't already zero, apply inertial decay to decelerate velocity\r\n const frameIndependentDecay = Math.pow(inertialDecayFactor, this._prevFrameTimeMs / FrameDurationAt60FPS);\r\n inputVelocity *= frameIndependentDecay;\r\n if (Math.abs(inputVelocity) <= Epsilon) {\r\n inputVelocity = 0;\r\n }\r\n }\r\n\r\n return inputVelocity;\r\n }\r\n}\r\n"]}
|
|
@@ -76,8 +76,6 @@ export declare class GeospatialCamera extends Camera {
|
|
|
76
76
|
private _tempNorth;
|
|
77
77
|
private _tempUp;
|
|
78
78
|
private _setOrientation;
|
|
79
|
-
/** The point around which the camera will geocentrically rotate. Uses center (pt we are anchored to) if no alternateRotationPt is defined */
|
|
80
|
-
private get _geocentricRotationPt();
|
|
81
79
|
/**
|
|
82
80
|
* If camera is actively in flight, will update the target properties and use up the remaining duration from original flyTo call
|
|
83
81
|
*
|
|
@@ -129,6 +127,7 @@ export declare class GeospatialCamera extends Camera {
|
|
|
129
127
|
private _zoomToPoint;
|
|
130
128
|
private _zoomAlongLookAt;
|
|
131
129
|
_checkInputs(): void;
|
|
130
|
+
private _wasCenterMovingLastFrame;
|
|
132
131
|
private _recalculateCenter;
|
|
133
132
|
attachControl(noPreventDefault?: boolean): void;
|
|
134
133
|
detachControl(): void;
|
|
@@ -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, Vector3Distance } from "../Maths/math.vector.functions.js";
|
|
7
|
+
import { Vector3CopyToRef, Vector3Distance, Vector3Dot } from "../Maths/math.vector.functions.js";
|
|
8
8
|
import { Clamp, NormalizeRadians } from "../Maths/math.scalar.functions.js";
|
|
9
9
|
import { InterpolatingBehavior } from "../Behaviors/Cameras/interpolatingBehavior.js";
|
|
10
10
|
/**
|
|
@@ -30,6 +30,7 @@ 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._wasCenterMovingLastFrame = false;
|
|
33
34
|
this._limits = new GeospatialLimits(options.planetRadius);
|
|
34
35
|
this._resetToDefault(this._limits);
|
|
35
36
|
this._flyingBehavior = new InterpolatingBehavior();
|
|
@@ -96,7 +97,7 @@ export class GeospatialCamera extends Camera {
|
|
|
96
97
|
this._yaw = Clamp(this._yaw, limits.yawMin, limits.yawMax);
|
|
97
98
|
this._pitch = Clamp(this._pitch, limits.pitchMin, limits.pitchMax);
|
|
98
99
|
this._radius = Clamp(this._radius, limits.radiusMin, limits.radiusMax);
|
|
99
|
-
|
|
100
|
+
ClampCenterFromPolesInPlace(this._center);
|
|
100
101
|
}
|
|
101
102
|
_setOrientation(yaw, pitch, radius, center) {
|
|
102
103
|
// Wrap yaw and pitch to [-π, π)
|
|
@@ -134,10 +135,6 @@ export class GeospatialCamera extends Camera {
|
|
|
134
135
|
this._position.copyFrom(this._tempPosition);
|
|
135
136
|
this._isViewMatrixDirty = true;
|
|
136
137
|
}
|
|
137
|
-
/** The point around which the camera will geocentrically rotate. Uses center (pt we are anchored to) if no alternateRotationPt is defined */
|
|
138
|
-
get _geocentricRotationPt() {
|
|
139
|
-
return this.movement.alternateRotationPt ?? this.center;
|
|
140
|
-
}
|
|
141
138
|
/**
|
|
142
139
|
* If camera is actively in flight, will update the target properties and use up the remaining duration from original flyTo call
|
|
143
140
|
*
|
|
@@ -149,7 +146,9 @@ export class GeospatialCamera extends Camera {
|
|
|
149
146
|
*/
|
|
150
147
|
updateFlyToDestination(targetYaw, targetPitch, targetRadius, targetCenter) {
|
|
151
148
|
this._flyToTargets.clear();
|
|
152
|
-
|
|
149
|
+
// For yaw, use shortest path to target.
|
|
150
|
+
const deltaYaw = targetYaw !== undefined ? NormalizeRadians(NormalizeRadians(targetYaw) - this._yaw) : 0;
|
|
151
|
+
this._flyToTargets.set("yaw", deltaYaw === 0 ? undefined : this._yaw + deltaYaw);
|
|
153
152
|
this._flyToTargets.set("pitch", targetPitch != undefined ? NormalizeRadians(targetPitch) : undefined);
|
|
154
153
|
this._flyToTargets.set("radius", targetRadius);
|
|
155
154
|
this._flyToTargets.set("center", targetCenter);
|
|
@@ -168,7 +167,9 @@ export class GeospatialCamera extends Camera {
|
|
|
168
167
|
*/
|
|
169
168
|
async flyToAsync(targetYaw, targetPitch, targetRadius, targetCenter, flightDurationMs = 1000, easingFunction, centerHopScale) {
|
|
170
169
|
this._flyToTargets.clear();
|
|
171
|
-
|
|
170
|
+
// For yaw, use shortest path to target.
|
|
171
|
+
const deltaYaw = targetYaw !== undefined ? NormalizeRadians(NormalizeRadians(targetYaw) - this._yaw) : 0;
|
|
172
|
+
this._flyToTargets.set("yaw", deltaYaw === 0 ? undefined : this._yaw + deltaYaw);
|
|
172
173
|
this._flyToTargets.set("pitch", targetPitch !== undefined ? NormalizeRadians(targetPitch) : undefined);
|
|
173
174
|
this._flyToTargets.set("radius", targetRadius);
|
|
174
175
|
this._flyToTargets.set("center", targetCenter);
|
|
@@ -276,8 +277,7 @@ export class GeospatialCamera extends Camera {
|
|
|
276
277
|
if (rotationDeltaCurrentFrame.x !== 0 || rotationDeltaCurrentFrame.y !== 0) {
|
|
277
278
|
const pitch = rotationDeltaCurrentFrame.x !== 0 ? Clamp(this._pitch + rotationDeltaCurrentFrame.x, 0, 0.5 * Math.PI - Epsilon) : this._pitch;
|
|
278
279
|
const yaw = rotationDeltaCurrentFrame.y !== 0 ? this._yaw + rotationDeltaCurrentFrame.y : this._yaw;
|
|
279
|
-
|
|
280
|
-
this._setOrientation(yaw, pitch, this._radius, this._geocentricRotationPt);
|
|
280
|
+
this._setOrientation(yaw, pitch, this._radius, this._center);
|
|
281
281
|
}
|
|
282
282
|
}
|
|
283
283
|
_getCenterAndRadiusFromZoomToPoint(targetPoint, distance, newCenter) {
|
|
@@ -333,35 +333,38 @@ export class GeospatialCamera extends Camera {
|
|
|
333
333
|
this.inputs.checkInputs();
|
|
334
334
|
// Let movement class handle all per-frame logic
|
|
335
335
|
this.movement.computeCurrentFrameDeltas();
|
|
336
|
-
let
|
|
336
|
+
let isCenterMoving = false;
|
|
337
337
|
if (this.movement.panDeltaCurrentFrame.lengthSquared() > 0) {
|
|
338
338
|
this._applyGeocentricTranslation();
|
|
339
|
-
|
|
339
|
+
// After a drag, recalculate the center point to ensure it's still on the surface.
|
|
340
|
+
isCenterMoving = true;
|
|
340
341
|
}
|
|
341
342
|
if (this.movement.rotationDeltaCurrentFrame.lengthSquared() > 0) {
|
|
342
343
|
this._applyGeocentricRotation();
|
|
343
344
|
}
|
|
344
345
|
if (Math.abs(this.movement.zoomDeltaCurrentFrame) > Epsilon) {
|
|
345
346
|
this._applyZoom();
|
|
346
|
-
|
|
347
|
+
isCenterMoving = true;
|
|
347
348
|
}
|
|
348
349
|
// After a movement impacting center or radius, recalculate the center point to ensure it's still on the surface.
|
|
349
|
-
|
|
350
|
+
this._recalculateCenter(isCenterMoving);
|
|
350
351
|
super._checkInputs();
|
|
351
352
|
}
|
|
352
|
-
_recalculateCenter() {
|
|
353
|
-
|
|
354
|
-
|
|
353
|
+
_recalculateCenter(isCenterMoving) {
|
|
354
|
+
const shouldRecalculateCenterAfterMove = this._wasCenterMovingLastFrame && !isCenterMoving;
|
|
355
|
+
this._wasCenterMovingLastFrame = isCenterMoving;
|
|
356
|
+
// Wait until movement impacting center is complete to avoid wasted raycasting
|
|
357
|
+
if (shouldRecalculateCenterAfterMove) {
|
|
355
358
|
const newCenter = this.movement.pickAlongVector(this._lookAtVector);
|
|
356
359
|
if (newCenter?.pickedPoint) {
|
|
357
360
|
// Direction from new center to origin
|
|
358
361
|
const centerToOrigin = TmpVectors.Vector3[4];
|
|
359
362
|
centerToOrigin.copyFrom(newCenter.pickedPoint).negateInPlace().normalize();
|
|
360
363
|
// Check if this direction aligns with camera's lookAt vector
|
|
361
|
-
const dotProduct =
|
|
364
|
+
const dotProduct = Vector3Dot(this._lookAtVector, centerToOrigin);
|
|
362
365
|
// Only update if the center is looking toward the origin (dot product > 0) to avoid a center on the opposite side of globe
|
|
363
366
|
if (dotProduct > 0) {
|
|
364
|
-
const newRadius =
|
|
367
|
+
const newRadius = Vector3Distance(this.position, newCenter.pickedPoint);
|
|
365
368
|
this._setOrientation(this._yaw, this._pitch, newRadius, newCenter.pickedPoint);
|
|
366
369
|
}
|
|
367
370
|
}
|