@pmndrs/klipp 0.0.0-stage → 0.14.0
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/LICENSE +21 -0
- package/README.md +72 -2
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/core/CameraState.d.ts +32 -0
- package/dist/core/CameraState.js +97 -0
- package/dist/core/EventDispatcher.d.ts +18 -0
- package/dist/core/EventDispatcher.js +28 -0
- package/dist/core/Klipp.d.ts +109 -0
- package/dist/core/Klipp.js +253 -0
- package/dist/core/TargetExtent.d.ts +11 -0
- package/dist/core/TargetExtent.js +54 -0
- package/dist/core/TargetPose.d.ts +13 -0
- package/dist/core/TargetPose.js +21 -0
- package/dist/core/VirtualCamera.d.ts +102 -0
- package/dist/core/VirtualCamera.js +290 -0
- package/dist/core/aim/HardLookAtAim.d.ts +10 -0
- package/dist/core/aim/HardLookAtAim.js +19 -0
- package/dist/core/aim/PanTiltAim.d.ts +26 -0
- package/dist/core/aim/PanTiltAim.js +38 -0
- package/dist/core/aim/RotateWithFollowTargetAim.d.ts +19 -0
- package/dist/core/aim/RotateWithFollowTargetAim.js +23 -0
- package/dist/core/aim/RotationComposerAim.d.ts +27 -0
- package/dist/core/aim/RotationComposerAim.js +27 -0
- package/dist/core/aim/hardLookAt.d.ts +4 -0
- package/dist/core/aim/hardLookAt.js +13 -0
- package/dist/core/aim/index.d.ts +11 -0
- package/dist/core/aim/lookRotation.d.ts +6 -0
- package/dist/core/aim/lookRotation.js +46 -0
- package/dist/core/aim/panTilt.d.ts +16 -0
- package/dist/core/aim/panTilt.js +121 -0
- package/dist/core/aim/rotateWithFollowTarget.d.ts +20 -0
- package/dist/core/aim/rotateWithFollowTarget.js +35 -0
- package/dist/core/aim/rotationComposer.d.ts +58 -0
- package/dist/core/aim/rotationComposer.js +284 -0
- package/dist/core/blend/BlendCurves.d.ts +19 -0
- package/dist/core/blend/BlendCurves.js +22 -0
- package/dist/core/blend/BlendDefinition.d.ts +21 -0
- package/dist/core/blend/BlendDefinition.js +9 -0
- package/dist/core/blend/BlendDriver.d.ts +23 -0
- package/dist/core/blend/BlendDriver.js +42 -0
- package/dist/core/blend/BlendHints.d.ts +9 -0
- package/dist/core/blend/BlendHints.js +13 -0
- package/dist/core/blend/blend.d.ts +41 -0
- package/dist/core/blend/blend.js +110 -0
- package/dist/core/blend/index.d.ts +6 -0
- package/dist/core/blend/lerpCameraState.d.ts +4 -0
- package/dist/core/blend/lerpCameraState.js +143 -0
- package/dist/core/body/BindingModes.d.ts +9 -0
- package/dist/core/body/BindingModes.js +11 -0
- package/dist/core/body/FollowBody.d.ts +24 -0
- package/dist/core/body/FollowBody.js +26 -0
- package/dist/core/body/HardLockToTargetBody.d.ts +17 -0
- package/dist/core/body/HardLockToTargetBody.js +20 -0
- package/dist/core/body/OrbitFollowBody.d.ts +47 -0
- package/dist/core/body/OrbitFollowBody.js +48 -0
- package/dist/core/body/PositionComposerBody.d.ts +28 -0
- package/dist/core/body/PositionComposerBody.js +27 -0
- package/dist/core/body/follow.d.ts +33 -0
- package/dist/core/body/follow.js +83 -0
- package/dist/core/body/hardLockToTarget.d.ts +17 -0
- package/dist/core/body/hardLockToTarget.js +26 -0
- package/dist/core/body/index.d.ts +17 -0
- package/dist/core/body/orbitFollow.d.ts +76 -0
- package/dist/core/body/orbitFollow.js +336 -0
- package/dist/core/body/positionComposer.d.ts +56 -0
- package/dist/core/body/positionComposer.js +207 -0
- package/dist/core/body/safeFromToRotation.d.ts +3 -0
- package/dist/core/body/safeFromToRotation.js +39 -0
- package/dist/core/body/threeRing.d.ts +28 -0
- package/dist/core/body/threeRing.js +100 -0
- package/dist/core/body/tracker.d.ts +42 -0
- package/dist/core/body/tracker.js +193 -0
- package/dist/core/damping/Damper.d.ts +11 -0
- package/dist/core/damping/Damper.js +22 -0
- package/dist/core/damping/damping.d.ts +30 -0
- package/dist/core/damping/damping.js +119 -0
- package/dist/core/damping/index.d.ts +5 -0
- package/dist/core/damping/predictor.d.ts +16 -0
- package/dist/core/damping/predictor.js +56 -0
- package/dist/core/debug/debugZones.d.ts +16 -0
- package/dist/core/debug/debugZones.js +38 -0
- package/dist/core/debug/index.d.ts +2 -0
- package/dist/core/extension/GroupFramingExtension.d.ts +26 -0
- package/dist/core/extension/GroupFramingExtension.js +24 -0
- package/dist/core/extension/LensExtension.d.ts +20 -0
- package/dist/core/extension/LensExtension.js +12 -0
- package/dist/core/extension/groupFraming.d.ts +62 -0
- package/dist/core/extension/groupFraming.js +271 -0
- package/dist/core/extension/index.d.ts +6 -0
- package/dist/core/extension/lens.d.ts +35 -0
- package/dist/core/extension/lens.js +57 -0
- package/dist/core/groups/ClearShot.d.ts +32 -0
- package/dist/core/groups/MixingCamera.d.ts +20 -0
- package/dist/core/groups/Sequencer.d.ts +24 -0
- package/dist/core/groups/StateDrivenCamera.d.ts +26 -0
- package/dist/core/groups/clearShotState.d.ts +32 -0
- package/dist/core/groups/index.d.ts +11 -0
- package/dist/core/groups/mixCameraStates.d.ts +13 -0
- package/dist/core/groups/sequencerState.d.ts +26 -0
- package/dist/core/groups/stateDrivenState.d.ts +28 -0
- package/dist/core/impulse/ImpulseField.d.ts +15 -0
- package/dist/core/impulse/ImpulseField.js +22 -0
- package/dist/core/impulse/ImpulseListenerNoise.d.ts +19 -0
- package/dist/core/impulse/ImpulseListenerNoise.js +29 -0
- package/dist/core/impulse/impulseListener.d.ts +13 -0
- package/dist/core/impulse/impulseListener.js +14 -0
- package/dist/core/impulse/impulses.d.ts +54 -0
- package/dist/core/impulse/impulses.js +84 -0
- package/dist/core/impulse/index.d.ts +6 -0
- package/dist/core/index.d.ts +20 -0
- package/dist/core/index.js +52 -0
- package/dist/core/input/InputAxis.d.ts +29 -0
- package/dist/core/input/InputAxis.js +28 -0
- package/dist/core/input/InputAxisOwner.d.ts +6 -0
- package/dist/core/input/InputAxisOwner.js +4 -0
- package/dist/core/input/InputController.d.ts +15 -0
- package/dist/core/input/InputController.js +24 -0
- package/dist/core/input/axis.d.ts +52 -0
- package/dist/core/input/axis.js +89 -0
- package/dist/core/input/consumedInput.d.ts +37 -0
- package/dist/core/input/consumedInput.js +34 -0
- package/dist/core/input/index.d.ts +9 -0
- package/dist/core/input/inputMapping.d.ts +46 -0
- package/dist/core/input/inputMapping.js +55 -0
- package/dist/core/input/shortestWrappedDelta.d.ts +2 -0
- package/dist/core/input/shortestWrappedDelta.js +11 -0
- package/dist/core/internal.d.ts +16 -0
- package/dist/core/internal.js +19 -0
- package/dist/core/klippState.d.ts +78 -0
- package/dist/core/klippState.js +124 -0
- package/dist/core/noise/BasicMultiChannelPerlinNoise.d.ts +21 -0
- package/dist/core/noise/BasicMultiChannelPerlinNoise.js +13 -0
- package/dist/core/noise/index.d.ts +3 -0
- package/dist/core/noise/perlinNoise.d.ts +36 -0
- package/dist/core/noise/perlinNoise.js +110 -0
- package/dist/core/params.d.ts +2 -0
- package/dist/core/params.js +12 -0
- package/dist/dom/DebugOverlay.d.ts +11 -0
- package/dist/dom/DebugOverlay.js +96 -0
- package/dist/dom/InputControllerDom.d.ts +15 -0
- package/dist/dom/InputControllerDom.js +31 -0
- package/dist/dom/InputSystem.d.ts +40 -0
- package/dist/dom/InputSystem.js +113 -0
- package/dist/dom/index.d.ts +3 -0
- package/dist/dom/index.js +5 -0
- package/dist/input-sources/buttonInput.d.ts +15 -0
- package/dist/input-sources/buttonInput.js +23 -0
- package/dist/input-sources/isInsideInteractiveArea.d.ts +9 -0
- package/dist/input-sources/isInsideInteractiveArea.js +11 -0
- package/dist/input-sources/mouse.d.ts +47 -0
- package/dist/input-sources/mouse.js +171 -0
- package/dist/input-sources/safariGesture.d.ts +32 -0
- package/dist/input-sources/safariGesture.js +107 -0
- package/dist/input-sources/suppressNativeGestures.d.ts +5 -0
- package/dist/input-sources/suppressNativeGestures.js +32 -0
- package/dist/input-sources/touch.d.ts +47 -0
- package/dist/input-sources/touch.js +173 -0
- package/dist/input-sources/wheel.d.ts +28 -0
- package/dist/input-sources/wheel.js +44 -0
- package/dist/react/CameraFrustumHelper.d.ts +13 -0
- package/dist/react/CameraFrustumHelper.js +32 -0
- package/dist/react/DebugZoneOverlay.d.ts +7 -0
- package/dist/react/DebugZoneOverlay.js +23 -0
- package/dist/react/Klipp.d.ts +20 -0
- package/dist/react/Klipp.js +47 -0
- package/dist/react/KlippContext.d.ts +5 -0
- package/dist/react/KlippContext.js +11 -0
- package/dist/react/VirtualCamera.d.ts +28 -0
- package/dist/react/VirtualCamera.js +81 -0
- package/dist/react/VirtualCameraContext.d.ts +11 -0
- package/dist/react/VirtualCameraContext.js +21 -0
- package/dist/react/aim/Aim.d.ts +11 -0
- package/dist/react/aim/Aim.js +14 -0
- package/dist/react/aim/HardLookAt.d.ts +10 -0
- package/dist/react/aim/HardLookAt.js +15 -0
- package/dist/react/aim/PanTilt.d.ts +31 -0
- package/dist/react/aim/PanTilt.js +38 -0
- package/dist/react/aim/RotateWithFollowTarget.d.ts +10 -0
- package/dist/react/aim/RotateWithFollowTarget.js +18 -0
- package/dist/react/aim/RotationComposer.d.ts +12 -0
- package/dist/react/aim/RotationComposer.js +34 -0
- package/dist/react/body/Body.d.ts +11 -0
- package/dist/react/body/Body.js +14 -0
- package/dist/react/body/CameraControls.d.ts +50 -0
- package/dist/react/body/CameraControls.js +106 -0
- package/dist/react/body/Follow.d.ts +10 -0
- package/dist/react/body/Follow.js +20 -0
- package/dist/react/body/HardLockToTarget.d.ts +10 -0
- package/dist/react/body/HardLockToTarget.js +18 -0
- package/dist/react/body/OrbitFollow.d.ts +25 -0
- package/dist/react/body/OrbitFollow.js +67 -0
- package/dist/react/body/PositionComposer.d.ts +12 -0
- package/dist/react/body/PositionComposer.js +32 -0
- package/dist/react/body/camera-controls.d.ts +2 -0
- package/dist/react/body/camera-controls.js +3 -0
- package/dist/react/extension/Extension.d.ts +7 -0
- package/dist/react/extension/Extension.js +10 -0
- package/dist/react/extension/GroupFraming.d.ts +14 -0
- package/dist/react/extension/GroupFraming.js +52 -0
- package/dist/react/extension/Lens.d.ts +7 -0
- package/dist/react/extension/Lens.js +31 -0
- package/dist/react/impulse/ImpulseListener.d.ts +12 -0
- package/dist/react/impulse/ImpulseListener.js +33 -0
- package/dist/react/index.d.ts +24 -0
- package/dist/react/index.js +24 -0
- package/dist/react/input/InputAxisOwnerContext.d.ts +3 -0
- package/dist/react/input/InputAxisOwnerContext.js +6 -0
- package/dist/react/input/InputController.d.ts +53 -0
- package/dist/react/input/InputController.js +115 -0
- package/dist/react/noise/BasicMultiChannelPerlin.d.ts +7 -0
- package/dist/react/noise/BasicMultiChannelPerlin.js +14 -0
- package/dist/react/noise/Noise.d.ts +5 -0
- package/dist/react/noise/Noise.js +6 -0
- package/dist/react/noise/useBasicMultiChannelPerlinNoise.d.ts +4 -0
- package/dist/react/noise/useBasicMultiChannelPerlinNoise.js +21 -0
- package/dist/react/useCameraTransitionEvent.d.ts +12 -0
- package/dist/react/useCameraTransitionEvent.js +14 -0
- package/dist/three/CameraFrustumHelperThree.d.ts +11 -0
- package/dist/three/CameraFrustumHelperThree.js +44 -0
- package/dist/three/KlippThree.d.ts +18 -0
- package/dist/three/KlippThree.js +50 -0
- package/dist/three/VirtualCameraThree.d.ts +35 -0
- package/dist/three/VirtualCameraThree.js +108 -0
- package/dist/three/aim/HardLookAtAimThree.d.ts +10 -0
- package/dist/three/aim/HardLookAtAimThree.js +14 -0
- package/dist/three/aim/PanTiltAimThree.d.ts +10 -0
- package/dist/three/aim/PanTiltAimThree.js +15 -0
- package/dist/three/aim/RotateWithFollowTargetAimThree.d.ts +11 -0
- package/dist/three/aim/RotateWithFollowTargetAimThree.js +15 -0
- package/dist/three/aim/RotationComposerAimThree.d.ts +26 -0
- package/dist/three/aim/RotationComposerAimThree.js +35 -0
- package/dist/three/body/CameraControlsBodyThree.d.ts +30 -0
- package/dist/three/body/CameraControlsBodyThree.js +54 -0
- package/dist/three/body/FollowBodyThree.d.ts +16 -0
- package/dist/three/body/FollowBodyThree.js +23 -0
- package/dist/three/body/HardLockToTargetBodyThree.d.ts +11 -0
- package/dist/three/body/HardLockToTargetBodyThree.js +14 -0
- package/dist/three/body/OrbitFollowBodyThree.d.ts +16 -0
- package/dist/three/body/OrbitFollowBodyThree.js +23 -0
- package/dist/three/body/OrbitFollowHelperThree.d.ts +23 -0
- package/dist/three/body/OrbitFollowHelperThree.js +85 -0
- package/dist/three/body/PositionComposerBodyThree.d.ts +24 -0
- package/dist/three/body/PositionComposerBodyThree.js +31 -0
- package/dist/three/camera.d.ts +10 -0
- package/dist/three/camera.js +39 -0
- package/dist/three/damping/Predictor.d.ts +12 -0
- package/dist/three/damping/Predictor.js +30 -0
- package/dist/three/damping/QuaternionDamper.d.ts +10 -0
- package/dist/three/damping/QuaternionDamper.js +28 -0
- package/dist/three/damping/Vector3Damper.d.ts +10 -0
- package/dist/three/damping/Vector3Damper.js +26 -0
- package/dist/three/extension/GroupFramingExtensionThree.d.ts +13 -0
- package/dist/three/extension/GroupFramingExtensionThree.js +23 -0
- package/dist/three/extension/TargetGroup.d.ts +32 -0
- package/dist/three/extension/TargetGroup.js +53 -0
- package/dist/three/index.d.ts +24 -0
- package/dist/three/index.js +25 -0
- package/dist/three/noise/BasicMultiChannelPerlinNoiseThree.d.ts +16 -0
- package/dist/three/noise/BasicMultiChannelPerlinNoiseThree.js +17 -0
- package/dist/three/readTargetExtent.d.ts +9 -0
- package/dist/three/readTargetExtent.js +25 -0
- package/dist/three/readTargetPose.d.ts +8 -0
- package/dist/three/readTargetPose.js +21 -0
- package/dist/three/resolve/Target.d.ts +17 -0
- package/dist/three/resolve/Target.js +62 -0
- package/dist/three/resolve/TargetRegistry.d.ts +27 -0
- package/dist/three/resolve/TargetRegistry.js +78 -0
- package/dist/three/resolve/resolveVector3.d.ts +12 -0
- package/dist/three/resolve/resolveVector3.js +29 -0
- package/package.json +120 -4
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { lookRotation } from "./lookRotation.js";
|
|
3
|
+
import { vec3 } from "math";
|
|
4
|
+
//#region src/core/aim/hardLookAt.ts
|
|
5
|
+
var hardLookAt_exports = /* @__PURE__ */ __exportAll({ update: () => update });
|
|
6
|
+
/** Rotates `out` so `targetPosition` is dead-center. */
|
|
7
|
+
function update(out, targetPosition) {
|
|
8
|
+
lookRotation(out.quaternion, out.position, targetPosition, out.referenceUp, out.quaternion);
|
|
9
|
+
vec3.copy(out.lookAtTarget, targetPosition);
|
|
10
|
+
out.hasLookAtTarget = true;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { hardLookAt_exports, update };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * as hardLookAt from './hardLookAt.js';
|
|
2
|
+
export { HardLookAtAim } from './HardLookAtAim.js';
|
|
3
|
+
export * as rotateWithFollowTarget from './rotateWithFollowTarget.js';
|
|
4
|
+
export type { RotateWithFollowTargetParams, RotateWithFollowTargetState } from './rotateWithFollowTarget.js';
|
|
5
|
+
export { RotateWithFollowTargetAim, type RotateWithFollowTargetOptions } from './RotateWithFollowTargetAim.js';
|
|
6
|
+
export * as rotationComposer from './rotationComposer.js';
|
|
7
|
+
export type { RotationComposerParams, RotationComposerState } from './rotationComposer.js';
|
|
8
|
+
export { RotationComposerAim } from './RotationComposerAim.js';
|
|
9
|
+
export * as panTilt from './panTilt.js';
|
|
10
|
+
export type { PanTiltState } from './panTilt.js';
|
|
11
|
+
export { PanTiltAim } from './PanTiltAim.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Quat, type Vec3 } from 'math';
|
|
2
|
+
/**
|
|
3
|
+
* The rotation looking from `position` at `target` with `up` on top. Looking along `up`, the screen's top comes
|
|
4
|
+
* from `previous`, so passing over the pole keeps the view steady.
|
|
5
|
+
*/
|
|
6
|
+
export declare function lookRotation(out: Quat, position: Vec3, target: Vec3, up: Vec3, previous: Quat): Quat;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { mat4, quat, vec3 } from "math";
|
|
2
|
+
//#region src/core/aim/lookRotation.ts
|
|
3
|
+
var yAxis = [
|
|
4
|
+
0,
|
|
5
|
+
1,
|
|
6
|
+
0
|
|
7
|
+
];
|
|
8
|
+
var forwardAxis = [
|
|
9
|
+
0,
|
|
10
|
+
0,
|
|
11
|
+
-1
|
|
12
|
+
];
|
|
13
|
+
var scratchDirection = [
|
|
14
|
+
0,
|
|
15
|
+
0,
|
|
16
|
+
0
|
|
17
|
+
];
|
|
18
|
+
var scratchCross = [
|
|
19
|
+
0,
|
|
20
|
+
0,
|
|
21
|
+
0
|
|
22
|
+
];
|
|
23
|
+
var scratchUp = [
|
|
24
|
+
0,
|
|
25
|
+
0,
|
|
26
|
+
0
|
|
27
|
+
];
|
|
28
|
+
var scratchLookMatrix = mat4.create();
|
|
29
|
+
var isParallel = (direction, up) => vec3.squaredLength(vec3.cross(scratchCross, direction, up)) < 1e-12 * vec3.squaredLength(direction);
|
|
30
|
+
/**
|
|
31
|
+
* The rotation looking from `position` at `target` with `up` on top. Looking along `up`, the screen's top comes
|
|
32
|
+
* from `previous`, so passing over the pole keeps the view steady.
|
|
33
|
+
*/
|
|
34
|
+
function lookRotation(out, position, target, up, previous) {
|
|
35
|
+
vec3.subtract(scratchDirection, target, position);
|
|
36
|
+
let screenUp = up;
|
|
37
|
+
if (isParallel(scratchDirection, up)) {
|
|
38
|
+
vec3.transformQuat(scratchUp, yAxis, previous);
|
|
39
|
+
if (isParallel(scratchDirection, scratchUp)) vec3.transformQuat(scratchUp, forwardAxis, previous);
|
|
40
|
+
screenUp = scratchUp;
|
|
41
|
+
}
|
|
42
|
+
mat4.targetTo(scratchLookMatrix, position, target, screenUp);
|
|
43
|
+
return quat.fromMat4(out, scratchLookMatrix);
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { lookRotation };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Quat, type Vec3 } from 'math';
|
|
2
|
+
import type { CameraState } from '../CameraState.js';
|
|
3
|
+
import { InputAxis } from '../input/InputAxis.js';
|
|
4
|
+
/** `pan` (yaw, wraps ±180°) and `tilt` (pitch, clamped) in degrees. */
|
|
5
|
+
export type PanTiltState = {
|
|
6
|
+
pan: InputAxis;
|
|
7
|
+
tilt: InputAxis;
|
|
8
|
+
};
|
|
9
|
+
export declare const createState: () => PanTiltState;
|
|
10
|
+
/** Advances both axes and writes the resulting rotation to `out`. Returns `true` while an axis still has to move. */
|
|
11
|
+
export declare function update(out: CameraState, state: PanTiltState, targetRotation: Quat | null, dt: number): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Seeds `pan`/`tilt` from `rotation`'s forward direction, relative to the reference frame. Call before
|
|
14
|
+
* any `applyDelta`, since it assumes both axes are still at their raw value.
|
|
15
|
+
*/
|
|
16
|
+
export declare function seed(state: PanTiltState, targetRotation: Quat | null, rotation: Quat, referenceUp: Vec3): void;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { InputAxis } from "../input/InputAxis.js";
|
|
3
|
+
import { degreesToRadians, quat, radiansToDegrees, vec3 } from "math";
|
|
4
|
+
//#region src/core/aim/panTilt.ts
|
|
5
|
+
var panTilt_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
createState: () => createState,
|
|
7
|
+
seed: () => seed,
|
|
8
|
+
update: () => update
|
|
9
|
+
});
|
|
10
|
+
var createState = () => ({
|
|
11
|
+
pan: new InputAxis({
|
|
12
|
+
range: [-180, 180],
|
|
13
|
+
wrap: true
|
|
14
|
+
}),
|
|
15
|
+
tilt: new InputAxis({ range: [-90, 90] })
|
|
16
|
+
});
|
|
17
|
+
var worldUp = [
|
|
18
|
+
0,
|
|
19
|
+
1,
|
|
20
|
+
0
|
|
21
|
+
];
|
|
22
|
+
var forwardAxis = [
|
|
23
|
+
0,
|
|
24
|
+
0,
|
|
25
|
+
-1
|
|
26
|
+
];
|
|
27
|
+
var epsilon = 1e-6;
|
|
28
|
+
var scratchFrame = [
|
|
29
|
+
0,
|
|
30
|
+
0,
|
|
31
|
+
0,
|
|
32
|
+
1
|
|
33
|
+
];
|
|
34
|
+
var scratchRotation = [
|
|
35
|
+
0,
|
|
36
|
+
0,
|
|
37
|
+
0,
|
|
38
|
+
1
|
|
39
|
+
];
|
|
40
|
+
var scratchAxisRotation = [
|
|
41
|
+
0,
|
|
42
|
+
0,
|
|
43
|
+
0,
|
|
44
|
+
1
|
|
45
|
+
];
|
|
46
|
+
var scratchEuler = [
|
|
47
|
+
0,
|
|
48
|
+
0,
|
|
49
|
+
0,
|
|
50
|
+
"yxz"
|
|
51
|
+
];
|
|
52
|
+
var scratchForward = [
|
|
53
|
+
0,
|
|
54
|
+
0,
|
|
55
|
+
0
|
|
56
|
+
];
|
|
57
|
+
var scratchTargetForward = [
|
|
58
|
+
0,
|
|
59
|
+
0,
|
|
60
|
+
0
|
|
61
|
+
];
|
|
62
|
+
var scratchA = [
|
|
63
|
+
0,
|
|
64
|
+
0,
|
|
65
|
+
0
|
|
66
|
+
];
|
|
67
|
+
var scratchB = [
|
|
68
|
+
0,
|
|
69
|
+
0,
|
|
70
|
+
0
|
|
71
|
+
];
|
|
72
|
+
var scratchRight = [
|
|
73
|
+
0,
|
|
74
|
+
0,
|
|
75
|
+
0
|
|
76
|
+
];
|
|
77
|
+
/** The frame pan and tilt are measured in: the target's rotation, or `referenceUp` alone. */
|
|
78
|
+
function referenceFrame(out, targetRotation, referenceUp) {
|
|
79
|
+
return targetRotation ? quat.copy(out, targetRotation) : quat.rotationTo(out, worldUp, referenceUp);
|
|
80
|
+
}
|
|
81
|
+
function projectOnPlane(out, v, normal) {
|
|
82
|
+
const lengthSq = vec3.squaredLength(normal);
|
|
83
|
+
if (lengthSq === 0) return vec3.copy(out, v);
|
|
84
|
+
return vec3.scaleAndAdd(out, v, normal, -vec3.dot(normal, v) / lengthSq);
|
|
85
|
+
}
|
|
86
|
+
/** Advances both axes and writes the resulting rotation to `out`. Returns `true` while an axis still has to move. */
|
|
87
|
+
function update(out, state, targetRotation, dt) {
|
|
88
|
+
const panMoving = state.pan.update(dt);
|
|
89
|
+
const tiltMoving = state.tilt.update(dt);
|
|
90
|
+
referenceFrame(scratchFrame, targetRotation, out.referenceUp);
|
|
91
|
+
scratchEuler[0] = -degreesToRadians(state.tilt.value);
|
|
92
|
+
scratchEuler[1] = -degreesToRadians(state.pan.value);
|
|
93
|
+
quat.multiply(out.quaternion, scratchFrame, quat.fromEuler(scratchRotation, scratchEuler));
|
|
94
|
+
return panMoving || tiltMoving;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Seeds `pan`/`tilt` from `rotation`'s forward direction, relative to the reference frame. Call before
|
|
98
|
+
* any `applyDelta`, since it assumes both axes are still at their raw value.
|
|
99
|
+
*/
|
|
100
|
+
function seed(state, targetRotation, rotation, referenceUp) {
|
|
101
|
+
referenceFrame(scratchFrame, targetRotation, referenceUp);
|
|
102
|
+
vec3.transformQuat(scratchForward, forwardAxis, scratchFrame);
|
|
103
|
+
vec3.transformQuat(scratchTargetForward, forwardAxis, rotation);
|
|
104
|
+
projectOnPlane(scratchA, scratchForward, referenceUp);
|
|
105
|
+
projectOnPlane(scratchB, scratchTargetForward, referenceUp);
|
|
106
|
+
let panRawDeg = 0;
|
|
107
|
+
if (vec3.squaredLength(scratchA) > epsilon && vec3.squaredLength(scratchB) > epsilon) panRawDeg = radiansToDegrees(vec3.signedAngle(scratchA, scratchB, referenceUp));
|
|
108
|
+
quat.setAxisAngle(scratchAxisRotation, referenceUp, degreesToRadians(panRawDeg));
|
|
109
|
+
vec3.transformQuat(scratchForward, scratchForward, scratchAxisRotation);
|
|
110
|
+
vec3.cross(scratchRight, referenceUp, scratchForward);
|
|
111
|
+
let tiltDeg = 0;
|
|
112
|
+
if (vec3.squaredLength(scratchRight) > epsilon) {
|
|
113
|
+
vec3.normalize(scratchRight, scratchRight);
|
|
114
|
+
tiltDeg = radiansToDegrees(vec3.signedAngle(scratchForward, scratchTargetForward, scratchRight));
|
|
115
|
+
}
|
|
116
|
+
const panDeg = -panRawDeg;
|
|
117
|
+
state.pan.applyDelta(panDeg - state.pan.value);
|
|
118
|
+
state.tilt.applyDelta(tiltDeg - state.tilt.value);
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
export { createState, panTilt_exports, seed, update };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Quat } from 'math';
|
|
2
|
+
import type { CameraState } from '../CameraState.js';
|
|
3
|
+
import type { DamperState, DampingConstant } from '../damping/damping.js';
|
|
4
|
+
export type RotateWithFollowTargetParams = {
|
|
5
|
+
/** Spring response time to the target's rotation (or `{into, from}` for asymmetric damping). */
|
|
6
|
+
damping: DampingConstant;
|
|
7
|
+
/** Caps how fast `damping` can close the gap, in radians/sec. */
|
|
8
|
+
maxSpeed: number;
|
|
9
|
+
};
|
|
10
|
+
/** Every setting from `settings`, or its default. */
|
|
11
|
+
export declare const createParams: (settings?: Partial<RotateWithFollowTargetParams>) => RotateWithFollowTargetParams;
|
|
12
|
+
export type RotateWithFollowTargetState = {
|
|
13
|
+
damper: DamperState;
|
|
14
|
+
primed: boolean;
|
|
15
|
+
};
|
|
16
|
+
export declare const createState: () => RotateWithFollowTargetState;
|
|
17
|
+
/** Turns `out` toward `targetRotation`, optionally damped. A `null` rotation leaves `out` as is. */
|
|
18
|
+
export declare function update(out: CameraState, state: RotateWithFollowTargetState, params: RotateWithFollowTargetParams, targetRotation: Quat | null, dt: number, justActivated: boolean): void;
|
|
19
|
+
/** Start the next activation from `rotation` instead of snapping to the target. */
|
|
20
|
+
export declare function prime(state: RotateWithFollowTargetState, params: RotateWithFollowTargetParams, rotation: Quat): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { createState as createState$1, dampQuaternion, reset } from "../damping/damping.js";
|
|
3
|
+
import { withDefaults } from "../params.js";
|
|
4
|
+
//#region src/core/aim/rotateWithFollowTarget.ts
|
|
5
|
+
var rotateWithFollowTarget_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
createParams: () => createParams,
|
|
7
|
+
createState: () => createState,
|
|
8
|
+
prime: () => prime,
|
|
9
|
+
update: () => update
|
|
10
|
+
});
|
|
11
|
+
/** Every setting from `settings`, or its default. */
|
|
12
|
+
var createParams = (settings) => withDefaults({
|
|
13
|
+
damping: 0,
|
|
14
|
+
maxSpeed: Infinity
|
|
15
|
+
}, settings);
|
|
16
|
+
var createState = () => ({
|
|
17
|
+
damper: createState$1(),
|
|
18
|
+
primed: false
|
|
19
|
+
});
|
|
20
|
+
/** Turns `out` toward `targetRotation`, optionally damped. A `null` rotation leaves `out` as is. */
|
|
21
|
+
function update(out, state, params, targetRotation, dt, justActivated) {
|
|
22
|
+
if (justActivated) {
|
|
23
|
+
if (state.primed) state.primed = false;
|
|
24
|
+
else reset(state.damper);
|
|
25
|
+
}
|
|
26
|
+
if (!targetRotation) return;
|
|
27
|
+
dampQuaternion(state.damper, out.quaternion, targetRotation, params.damping, dt, params.maxSpeed);
|
|
28
|
+
}
|
|
29
|
+
/** Start the next activation from `rotation` instead of snapping to the target. */
|
|
30
|
+
function prime(state, params, rotation) {
|
|
31
|
+
dampQuaternion(state.damper, rotation, rotation, params.damping, 0);
|
|
32
|
+
state.primed = true;
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { createParams, createState, prime, rotateWithFollowTarget_exports, update };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type Quat, type Vec3 } from 'math';
|
|
2
|
+
import type { CameraState } from '../CameraState.js';
|
|
3
|
+
import type { TargetPose } from '../TargetPose.js';
|
|
4
|
+
import type { DamperState, DampingConstant } from '../damping/damping.js';
|
|
5
|
+
import type { PredictorState } from '../damping/predictor.js';
|
|
6
|
+
export type RotationComposerParams = {
|
|
7
|
+
/** Where the target should land on screen: `[x, y]`, `0` = center, `±1` = edge. */
|
|
8
|
+
screenPosition: [number, number];
|
|
9
|
+
/** Viewport width divided by height. */
|
|
10
|
+
aspect: number;
|
|
11
|
+
/** Allowed target drift from `screenPosition` before the camera reacts. */
|
|
12
|
+
deadZone: [number, number];
|
|
13
|
+
/** Response time when the target leaves the `deadZone`. */
|
|
14
|
+
damping: DampingConstant;
|
|
15
|
+
/** Maximum damping speed, in radians/sec. */
|
|
16
|
+
maxSpeed: number;
|
|
17
|
+
/** Maximum allowed target drift, enforced immediately. */
|
|
18
|
+
hardLimit: [number, number];
|
|
19
|
+
/** Offset from the target, in the target's local space. */
|
|
20
|
+
targetOffset: Vec3;
|
|
21
|
+
/** Seconds to aim ahead of the target's current position. */
|
|
22
|
+
lookaheadTime: number;
|
|
23
|
+
/** Smoothing time for the lookahead velocity estimate. */
|
|
24
|
+
lookaheadSmoothing: number;
|
|
25
|
+
/** Whether lookahead ignores vertical movement. */
|
|
26
|
+
lookaheadIgnoreY: boolean;
|
|
27
|
+
};
|
|
28
|
+
/** Every setting from `settings`, or its default. */
|
|
29
|
+
export declare const createParams: (settings?: Partial<RotationComposerParams>) => RotationComposerParams;
|
|
30
|
+
export type RotationComposerState = {
|
|
31
|
+
damper: DamperState;
|
|
32
|
+
/** Damps the published look-at direction as a rotation to avoid degenerate intermediate points. */
|
|
33
|
+
lookAtDirectionDamper: DamperState;
|
|
34
|
+
lookAtDistanceDamper: DamperState;
|
|
35
|
+
publishedLookRotation: Quat;
|
|
36
|
+
publishedDistance: number;
|
|
37
|
+
/** Last desired rotation, kept while the target stays inside the dead zone. */
|
|
38
|
+
lastActiveDesiredRotation: Quat;
|
|
39
|
+
hasActiveDesiredRotation: boolean;
|
|
40
|
+
predictor: PredictorState;
|
|
41
|
+
primed: boolean;
|
|
42
|
+
/** Activation seen while the target was unresolved, applied on the first frame that has one. */
|
|
43
|
+
activationPending: boolean;
|
|
44
|
+
/** Whether that pending activation was primed. */
|
|
45
|
+
activationPrimed: boolean;
|
|
46
|
+
};
|
|
47
|
+
export declare const createState: () => RotationComposerState;
|
|
48
|
+
/** Only extents with a dead zone or hard limit are read, so callers can skip resolving them otherwise. */
|
|
49
|
+
export declare const needsExtent: (params: RotationComposerParams) => boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Rotates `out` to place the target at `screenPosition`. A `null` target leaves `out` as is; a target
|
|
52
|
+
* without rotation counts as identity for `targetOffset`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function update(out: CameraState, state: RotationComposerState, params: RotationComposerParams, targetPose: TargetPose | null, dt: number, justActivated: boolean): void;
|
|
55
|
+
/** Restart the lookahead history, for when the target switches to a different object. */
|
|
56
|
+
export declare function retarget(state: RotationComposerState): void;
|
|
57
|
+
/** Start the next activation from `rotation` instead of snapping to the target. */
|
|
58
|
+
export declare function prime(state: RotationComposerState, params: RotationComposerParams, rotation: Quat): void;
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { createState as createState$1, damp, dampQuaternion, reset } from "../damping/damping.js";
|
|
3
|
+
import { project } from "../TargetExtent.js";
|
|
4
|
+
import { lookRotation } from "./lookRotation.js";
|
|
5
|
+
import { withDefaults } from "../params.js";
|
|
6
|
+
import { addPosition, create, predictDelta, reset as reset$1 } from "../damping/predictor.js";
|
|
7
|
+
import { clamp, degreesToRadians, quat, vec3, vec4 } from "math";
|
|
8
|
+
//#region src/core/aim/rotationComposer.ts
|
|
9
|
+
var rotationComposer_exports = /* @__PURE__ */ __exportAll({
|
|
10
|
+
createParams: () => createParams,
|
|
11
|
+
createState: () => createState,
|
|
12
|
+
needsExtent: () => needsExtent,
|
|
13
|
+
prime: () => prime,
|
|
14
|
+
retarget: () => retarget,
|
|
15
|
+
update: () => update
|
|
16
|
+
});
|
|
17
|
+
/** Every setting from `settings`, or its default. */
|
|
18
|
+
var createParams = (settings) => withDefaults({
|
|
19
|
+
screenPosition: [0, 0],
|
|
20
|
+
aspect: 1,
|
|
21
|
+
deadZone: [0, 0],
|
|
22
|
+
damping: 0,
|
|
23
|
+
maxSpeed: Infinity,
|
|
24
|
+
hardLimit: [0, 0],
|
|
25
|
+
targetOffset: [
|
|
26
|
+
0,
|
|
27
|
+
0,
|
|
28
|
+
0
|
|
29
|
+
],
|
|
30
|
+
lookaheadTime: 0,
|
|
31
|
+
lookaheadSmoothing: 1,
|
|
32
|
+
lookaheadIgnoreY: false
|
|
33
|
+
}, settings);
|
|
34
|
+
var createState = () => ({
|
|
35
|
+
damper: createState$1(),
|
|
36
|
+
lookAtDirectionDamper: createState$1(),
|
|
37
|
+
lookAtDistanceDamper: createState$1(),
|
|
38
|
+
publishedLookRotation: [
|
|
39
|
+
0,
|
|
40
|
+
0,
|
|
41
|
+
0,
|
|
42
|
+
1
|
|
43
|
+
],
|
|
44
|
+
publishedDistance: 0,
|
|
45
|
+
lastActiveDesiredRotation: [
|
|
46
|
+
0,
|
|
47
|
+
0,
|
|
48
|
+
0,
|
|
49
|
+
1
|
|
50
|
+
],
|
|
51
|
+
hasActiveDesiredRotation: false,
|
|
52
|
+
predictor: create(),
|
|
53
|
+
primed: false,
|
|
54
|
+
activationPending: false,
|
|
55
|
+
activationPrimed: false
|
|
56
|
+
});
|
|
57
|
+
/** Only extents with a dead zone or hard limit are read, so callers can skip resolving them otherwise. */
|
|
58
|
+
var needsExtent = (params) => params.deadZone[0] > 0 || params.deadZone[1] > 0 || params.hardLimit[0] > 0 || params.hardLimit[1] > 0;
|
|
59
|
+
/** Matches `damp`'s own `epsilon`: the gap at which it declares the distance arrived. */
|
|
60
|
+
var DISTANCE_EPSILON = 1e-4;
|
|
61
|
+
var forwardAxis = [
|
|
62
|
+
0,
|
|
63
|
+
0,
|
|
64
|
+
-1
|
|
65
|
+
];
|
|
66
|
+
var rightAxis = [
|
|
67
|
+
1,
|
|
68
|
+
0,
|
|
69
|
+
0
|
|
70
|
+
];
|
|
71
|
+
var upAxis = [
|
|
72
|
+
0,
|
|
73
|
+
1,
|
|
74
|
+
0
|
|
75
|
+
];
|
|
76
|
+
var scratchTarget = [
|
|
77
|
+
0,
|
|
78
|
+
0,
|
|
79
|
+
0
|
|
80
|
+
];
|
|
81
|
+
var scratchTargetRotation = [
|
|
82
|
+
0,
|
|
83
|
+
0,
|
|
84
|
+
0,
|
|
85
|
+
1
|
|
86
|
+
];
|
|
87
|
+
var scratchLookaheadDelta = [
|
|
88
|
+
0,
|
|
89
|
+
0,
|
|
90
|
+
0
|
|
91
|
+
];
|
|
92
|
+
var scratchOffset = [
|
|
93
|
+
0,
|
|
94
|
+
0,
|
|
95
|
+
0
|
|
96
|
+
];
|
|
97
|
+
var scratchLookRotation = [
|
|
98
|
+
0,
|
|
99
|
+
0,
|
|
100
|
+
0,
|
|
101
|
+
1
|
|
102
|
+
];
|
|
103
|
+
var scratchDesiredRotation = [
|
|
104
|
+
0,
|
|
105
|
+
0,
|
|
106
|
+
0,
|
|
107
|
+
1
|
|
108
|
+
];
|
|
109
|
+
var scratchHardLimitRotation = [
|
|
110
|
+
0,
|
|
111
|
+
0,
|
|
112
|
+
0,
|
|
113
|
+
1
|
|
114
|
+
];
|
|
115
|
+
var scratchInverse = [
|
|
116
|
+
0,
|
|
117
|
+
0,
|
|
118
|
+
0,
|
|
119
|
+
1
|
|
120
|
+
];
|
|
121
|
+
var scratchLocalDir = [
|
|
122
|
+
0,
|
|
123
|
+
0,
|
|
124
|
+
0
|
|
125
|
+
];
|
|
126
|
+
var scratchDesiredDir = [
|
|
127
|
+
0,
|
|
128
|
+
0,
|
|
129
|
+
0
|
|
130
|
+
];
|
|
131
|
+
var scratchDelta = [
|
|
132
|
+
0,
|
|
133
|
+
0,
|
|
134
|
+
0,
|
|
135
|
+
1
|
|
136
|
+
];
|
|
137
|
+
var scratchRight = [
|
|
138
|
+
0,
|
|
139
|
+
0,
|
|
140
|
+
0
|
|
141
|
+
];
|
|
142
|
+
var scratchUp = [
|
|
143
|
+
0,
|
|
144
|
+
0,
|
|
145
|
+
0
|
|
146
|
+
];
|
|
147
|
+
var scratchExtents = [0, 0];
|
|
148
|
+
/** `[x, y, depth]` of a world point in the camera's screen space. `depth <= 0` means behind the camera. */
|
|
149
|
+
var scratchScreenPoint = [
|
|
150
|
+
0,
|
|
151
|
+
0,
|
|
152
|
+
0
|
|
153
|
+
];
|
|
154
|
+
function computeScreenPoint(position, rotation, worldPoint, tanHalfFovH, tanHalfFovV) {
|
|
155
|
+
vec3.subtract(scratchLocalDir, worldPoint, position);
|
|
156
|
+
vec3.transformQuat(scratchLocalDir, scratchLocalDir, quat.conjugate(scratchInverse, rotation));
|
|
157
|
+
const depth = -scratchLocalDir[2];
|
|
158
|
+
scratchScreenPoint[0] = scratchLocalDir[0] / depth / tanHalfFovH;
|
|
159
|
+
scratchScreenPoint[1] = scratchLocalDir[1] / depth / tanHalfFovV;
|
|
160
|
+
scratchScreenPoint[2] = depth;
|
|
161
|
+
return scratchScreenPoint;
|
|
162
|
+
}
|
|
163
|
+
/** Turns `lookAt`, which looks at the target, to place it at screen point `(desiredX, desiredY)` instead. */
|
|
164
|
+
function composeRotationForScreenPoint(out, lookAt, desiredX, desiredY, tanHalfFovH, tanHalfFovV) {
|
|
165
|
+
quat.copy(out, lookAt);
|
|
166
|
+
if (desiredX === 0 && desiredY === 0) return;
|
|
167
|
+
vec3.normalize(scratchDesiredDir, vec3.set(scratchDesiredDir, desiredX * tanHalfFovH, desiredY * tanHalfFovV, -1));
|
|
168
|
+
vec3.cross(scratchLocalDir, scratchDesiredDir, forwardAxis);
|
|
169
|
+
const w = vec3.dot(scratchDesiredDir, forwardAxis) + 1;
|
|
170
|
+
quat.normalize(scratchDelta, quat.set(scratchDelta, scratchLocalDir[0], scratchLocalDir[1], scratchLocalDir[2], w));
|
|
171
|
+
quat.multiply(out, out, scratchDelta);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Rotates `out` to place the target at `screenPosition`. A `null` target leaves `out` as is; a target
|
|
175
|
+
* without rotation counts as identity for `targetOffset`.
|
|
176
|
+
*/
|
|
177
|
+
function update(out, state, params, targetPose, dt, justActivated) {
|
|
178
|
+
if (justActivated) {
|
|
179
|
+
state.activationPending = true;
|
|
180
|
+
state.activationPrimed = state.primed;
|
|
181
|
+
state.primed = false;
|
|
182
|
+
}
|
|
183
|
+
if (!targetPose) return;
|
|
184
|
+
const activating = state.activationPending;
|
|
185
|
+
const skipReset = activating && state.activationPrimed;
|
|
186
|
+
state.activationPending = false;
|
|
187
|
+
const { extent } = targetPose;
|
|
188
|
+
const target = vec3.copy(scratchTarget, targetPose.position);
|
|
189
|
+
if (activating) reset$1(state.predictor);
|
|
190
|
+
addPosition(state.predictor, target, dt, params.lookaheadSmoothing);
|
|
191
|
+
if (params.lookaheadTime > 0) {
|
|
192
|
+
predictDelta(scratchLookaheadDelta, state.predictor, params.lookaheadTime);
|
|
193
|
+
if (params.lookaheadIgnoreY) scratchLookaheadDelta[1] = 0;
|
|
194
|
+
vec3.add(target, target, scratchLookaheadDelta);
|
|
195
|
+
}
|
|
196
|
+
if (targetPose.hasRotation) quat.copy(scratchTargetRotation, targetPose.rotation);
|
|
197
|
+
else quat.identity(scratchTargetRotation);
|
|
198
|
+
vec3.add(target, target, vec3.transformQuat(scratchOffset, params.targetOffset, scratchTargetRotation));
|
|
199
|
+
const { position, referenceUp, quaternion: rotation, rotationDampingBypass: bypass } = out;
|
|
200
|
+
if (!activating && bypass[3] !== 1) {
|
|
201
|
+
quat.normalize(rotation, quat.multiply(rotation, bypass, rotation));
|
|
202
|
+
quat.normalize(state.publishedLookRotation, quat.multiply(state.publishedLookRotation, bypass, state.publishedLookRotation));
|
|
203
|
+
quat.normalize(state.lastActiveDesiredRotation, quat.multiply(state.lastActiveDesiredRotation, bypass, state.lastActiveDesiredRotation));
|
|
204
|
+
}
|
|
205
|
+
if (activating) {
|
|
206
|
+
reset(state.lookAtDirectionDamper);
|
|
207
|
+
reset(state.lookAtDistanceDamper);
|
|
208
|
+
}
|
|
209
|
+
lookRotation(scratchLookRotation, position, target, referenceUp, rotation);
|
|
210
|
+
dampQuaternion(state.lookAtDirectionDamper, state.publishedLookRotation, scratchLookRotation, params.damping, dt, params.maxSpeed);
|
|
211
|
+
const targetDistance = vec3.distance(position, target);
|
|
212
|
+
state.lookAtDistanceDamper.value = state.publishedDistance;
|
|
213
|
+
state.publishedDistance = damp(state.lookAtDistanceDamper, targetDistance, params.damping, dt).value;
|
|
214
|
+
if (vec4.exactEquals(state.publishedLookRotation, scratchLookRotation) && Math.abs(state.publishedDistance - targetDistance) < DISTANCE_EPSILON) vec3.copy(out.lookAtTarget, target);
|
|
215
|
+
else {
|
|
216
|
+
vec3.transformQuat(out.lookAtTarget, forwardAxis, state.publishedLookRotation);
|
|
217
|
+
vec3.scaleAndAdd(out.lookAtTarget, position, out.lookAtTarget, state.publishedDistance);
|
|
218
|
+
}
|
|
219
|
+
out.hasLookAtTarget = true;
|
|
220
|
+
const halfFovV = degreesToRadians(out.fov) / 2;
|
|
221
|
+
const tanHalfFovV = Math.tan(halfFovV);
|
|
222
|
+
const tanHalfFovH = tanHalfFovV * params.aspect;
|
|
223
|
+
const { screenPosition, deadZone, hardLimit } = params;
|
|
224
|
+
let desiredX = screenPosition[0];
|
|
225
|
+
let desiredY = screenPosition[1];
|
|
226
|
+
let insideDeadZone = false;
|
|
227
|
+
if (!activating && (deadZone[0] > 0 || deadZone[1] > 0)) {
|
|
228
|
+
const [screenX, screenY, depth] = computeScreenPoint(position, rotation, target, tanHalfFovH, tanHalfFovV);
|
|
229
|
+
if (depth > 1e-6) {
|
|
230
|
+
const halfWidth = deadZone[0];
|
|
231
|
+
const halfHeight = deadZone[1];
|
|
232
|
+
vec3.transformQuat(scratchRight, rightAxis, rotation);
|
|
233
|
+
vec3.transformQuat(scratchUp, upAxis, rotation);
|
|
234
|
+
project(scratchExtents, extent, scratchRight, scratchUp);
|
|
235
|
+
const extentX = Math.min(scratchExtents[0] / depth / tanHalfFovH, halfWidth);
|
|
236
|
+
const extentY = Math.min(scratchExtents[1] / depth / tanHalfFovV, halfHeight);
|
|
237
|
+
const errorX = screenX - screenPosition[0];
|
|
238
|
+
const errorY = screenY - screenPosition[1];
|
|
239
|
+
const edgeErrorX = errorX + Math.sign(errorX) * extentX;
|
|
240
|
+
const edgeErrorY = errorY + Math.sign(errorY) * extentY;
|
|
241
|
+
insideDeadZone = Math.abs(edgeErrorX) <= halfWidth && Math.abs(edgeErrorY) <= halfHeight;
|
|
242
|
+
if (!insideDeadZone) {
|
|
243
|
+
desiredX = screenPosition[0] + clamp(edgeErrorX, -halfWidth, halfWidth) - Math.sign(errorX) * extentX;
|
|
244
|
+
desiredY = screenPosition[1] + clamp(edgeErrorY, -halfHeight, halfHeight) - Math.sign(errorY) * extentY;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (!insideDeadZone) {
|
|
249
|
+
composeRotationForScreenPoint(scratchDesiredRotation, scratchLookRotation, desiredX, desiredY, tanHalfFovH, tanHalfFovV);
|
|
250
|
+
quat.copy(state.lastActiveDesiredRotation, scratchDesiredRotation);
|
|
251
|
+
state.hasActiveDesiredRotation = true;
|
|
252
|
+
} else if (state.hasActiveDesiredRotation) quat.copy(scratchDesiredRotation, state.lastActiveDesiredRotation);
|
|
253
|
+
else quat.copy(scratchDesiredRotation, rotation);
|
|
254
|
+
if (activating && !skipReset) reset(state.damper);
|
|
255
|
+
dampQuaternion(state.damper, rotation, scratchDesiredRotation, params.damping, dt, params.maxSpeed);
|
|
256
|
+
if (hardLimit[0] <= 0 && hardLimit[1] <= 0) return;
|
|
257
|
+
const [screenX, screenY, depth] = computeScreenPoint(position, rotation, target, tanHalfFovH, tanHalfFovV);
|
|
258
|
+
if (depth <= 1e-6) return;
|
|
259
|
+
const halfLimitWidth = hardLimit[0];
|
|
260
|
+
const halfLimitHeight = hardLimit[1];
|
|
261
|
+
vec3.transformQuat(scratchRight, rightAxis, rotation);
|
|
262
|
+
vec3.transformQuat(scratchUp, upAxis, rotation);
|
|
263
|
+
project(scratchExtents, extent, scratchRight, scratchUp);
|
|
264
|
+
const limitExtentX = Math.min(scratchExtents[0] / depth / tanHalfFovH, halfLimitWidth);
|
|
265
|
+
const limitExtentY = Math.min(scratchExtents[1] / depth / tanHalfFovV, halfLimitHeight);
|
|
266
|
+
const errorX = screenX - screenPosition[0];
|
|
267
|
+
const errorY = screenY - screenPosition[1];
|
|
268
|
+
const edgeErrorX = errorX + Math.sign(errorX) * limitExtentX;
|
|
269
|
+
const edgeErrorY = errorY + Math.sign(errorY) * limitExtentY;
|
|
270
|
+
if (Math.abs(edgeErrorX) <= halfLimitWidth && Math.abs(edgeErrorY) <= halfLimitHeight) return;
|
|
271
|
+
composeRotationForScreenPoint(scratchHardLimitRotation, scratchLookRotation, screenPosition[0] + clamp(edgeErrorX, -halfLimitWidth, halfLimitWidth) - Math.sign(errorX) * limitExtentX, screenPosition[1] + clamp(edgeErrorY, -halfLimitHeight, halfLimitHeight) - Math.sign(errorY) * limitExtentY, tanHalfFovH, tanHalfFovV);
|
|
272
|
+
quat.copy(rotation, scratchHardLimitRotation);
|
|
273
|
+
}
|
|
274
|
+
/** Restart the lookahead history, for when the target switches to a different object. */
|
|
275
|
+
function retarget(state) {
|
|
276
|
+
reset$1(state.predictor);
|
|
277
|
+
}
|
|
278
|
+
/** Start the next activation from `rotation` instead of snapping to the target. */
|
|
279
|
+
function prime(state, params, rotation) {
|
|
280
|
+
dampQuaternion(state.damper, rotation, rotation, params.damping, 0);
|
|
281
|
+
state.primed = true;
|
|
282
|
+
}
|
|
283
|
+
//#endregion
|
|
284
|
+
export { createParams, createState, needsExtent, prime, retarget, rotationComposer_exports, update };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Maps linear progress `t` in `[0, 1]` to eased progress. */
|
|
2
|
+
export type Ease = (t: number) => number;
|
|
3
|
+
/** Named blend curves. Pass a custom `Ease` for other shapes. */
|
|
4
|
+
export declare const BlendCurves: {
|
|
5
|
+
/** Snaps at the end of the blend. */
|
|
6
|
+
readonly cut: Ease;
|
|
7
|
+
/** Constant-rate blend. */
|
|
8
|
+
readonly linear: Ease;
|
|
9
|
+
/** Smooth S-shaped blend. */
|
|
10
|
+
readonly easeInOut: Ease;
|
|
11
|
+
/** Eased departure, fast arrival. */
|
|
12
|
+
readonly easeIn: Ease;
|
|
13
|
+
/** Fast departure, eased arrival. */
|
|
14
|
+
readonly easeOut: Ease;
|
|
15
|
+
/** Abrupt departure, smooth arrival. */
|
|
16
|
+
readonly cubicOut: Ease;
|
|
17
|
+
/** Smooth departure, abrupt arrival. */
|
|
18
|
+
readonly cubicIn: Ease;
|
|
19
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { smoothstep } from "math";
|
|
2
|
+
import { easing } from "math/time";
|
|
3
|
+
//#region src/core/blend/BlendCurves.ts
|
|
4
|
+
/** Named blend curves. Pass a custom `Ease` for other shapes. */
|
|
5
|
+
var BlendCurves = {
|
|
6
|
+
/** Snaps at the end of the blend. */
|
|
7
|
+
cut: ((t) => t < 1 ? 0 : 1),
|
|
8
|
+
/** Constant-rate blend. */
|
|
9
|
+
linear: easing.linear,
|
|
10
|
+
/** Smooth S-shaped blend. */
|
|
11
|
+
easeInOut: ((t) => smoothstep(0, 1, t)),
|
|
12
|
+
/** Eased departure, fast arrival. */
|
|
13
|
+
easeIn: ((t) => t * t),
|
|
14
|
+
/** Fast departure, eased arrival. */
|
|
15
|
+
easeOut: ((t) => t * (2 - t)),
|
|
16
|
+
/** Abrupt departure, smooth arrival. */
|
|
17
|
+
cubicOut: easing.cubicOut,
|
|
18
|
+
/** Smooth departure, abrupt arrival. */
|
|
19
|
+
cubicIn: easing.cubicIn
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { BlendCurves };
|