@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,22 @@
|
|
|
1
|
+
import { createState, damp, reset } from "./damping.js";
|
|
2
|
+
//#region src/core/damping/Damper.ts
|
|
3
|
+
/** Stateful wrapper over `damp`. */
|
|
4
|
+
var Damper = class {
|
|
5
|
+
state = createState();
|
|
6
|
+
get velocity() {
|
|
7
|
+
return this.state.velocity;
|
|
8
|
+
}
|
|
9
|
+
set velocity(value) {
|
|
10
|
+
this.state.velocity = value;
|
|
11
|
+
}
|
|
12
|
+
update(current, target, dampingTime, dt, maxSpeed = Infinity, epsilon = 1e-4) {
|
|
13
|
+
this.state.value = current;
|
|
14
|
+
return damp(this.state, target, dampingTime, dt, maxSpeed, epsilon).value;
|
|
15
|
+
}
|
|
16
|
+
/** Reset the spring state so the next call snaps to the target again. */
|
|
17
|
+
reset() {
|
|
18
|
+
reset(this.state);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { Damper };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Quat, type Vec3 } from 'math';
|
|
2
|
+
import { type Spring } from 'math/time';
|
|
3
|
+
/** Damping time, optionally asymmetric for widening and narrowing gaps. */
|
|
4
|
+
export type DampingConstant = number | {
|
|
5
|
+
into: number;
|
|
6
|
+
from: number;
|
|
7
|
+
};
|
|
8
|
+
/** Damper memory: a math `Spring<number>` plus asymmetric damping and snap state. */
|
|
9
|
+
export type DamperState = Spring<number> & {
|
|
10
|
+
previousDistance: number;
|
|
11
|
+
hasUpdated: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare const createState: (value?: number) => DamperState;
|
|
14
|
+
/** Reset the state so the next call snaps to the target. */
|
|
15
|
+
export declare function reset(state: DamperState): void;
|
|
16
|
+
/** Critically damped spring step with target snapping. Mutates and returns `state`. */
|
|
17
|
+
export declare function damp(state: DamperState, target: number, damping: DampingConstant, dt: number, maxSpeed?: number, epsilon?: number): DamperState;
|
|
18
|
+
/** One damper per Cartesian component. */
|
|
19
|
+
export type Vector3DamperState = {
|
|
20
|
+
x: DamperState;
|
|
21
|
+
y: DamperState;
|
|
22
|
+
z: DamperState;
|
|
23
|
+
};
|
|
24
|
+
export declare const createVector3State: () => Vector3DamperState;
|
|
25
|
+
/** Reset all three component dampers. */
|
|
26
|
+
export declare function resetVector3(state: Vector3DamperState): void;
|
|
27
|
+
/** Damps the components of `out` toward `target` independently. Mutates and returns `out`. */
|
|
28
|
+
export declare function dampVector3(state: Vector3DamperState, out: Vec3, target: Vec3, damping: DampingConstant, dt: number, maxSpeed?: number): Vec3;
|
|
29
|
+
/** Damps `out` toward `target` along the shortest angular delta. Mutates and returns `out`. */
|
|
30
|
+
export declare function dampQuaternion(state: DamperState, out: Quat, target: Quat, damping: DampingConstant, dt: number, maxSpeed?: number): Quat;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { clamp, quat, vec3, vec4 } from "math";
|
|
3
|
+
import { spring } from "math/time";
|
|
4
|
+
//#region src/core/damping/damping.ts
|
|
5
|
+
var damping_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
createState: () => createState,
|
|
7
|
+
createVector3State: () => createVector3State,
|
|
8
|
+
damp: () => damp,
|
|
9
|
+
dampQuaternion: () => dampQuaternion,
|
|
10
|
+
dampVector3: () => dampVector3,
|
|
11
|
+
reset: () => reset,
|
|
12
|
+
resetVector3: () => resetVector3
|
|
13
|
+
});
|
|
14
|
+
var createState = (value = 0) => ({
|
|
15
|
+
value,
|
|
16
|
+
velocity: 0,
|
|
17
|
+
previousDistance: 0,
|
|
18
|
+
hasUpdated: false
|
|
19
|
+
});
|
|
20
|
+
/** Reset the state so the next call snaps to the target. */
|
|
21
|
+
function reset(state) {
|
|
22
|
+
state.velocity = 0;
|
|
23
|
+
state.previousDistance = 0;
|
|
24
|
+
state.hasUpdated = false;
|
|
25
|
+
}
|
|
26
|
+
/** Critically damped spring step with target snapping. Mutates and returns `state`. */
|
|
27
|
+
function damp(state, target, damping, dt, maxSpeed = Infinity, epsilon = 1e-4) {
|
|
28
|
+
if (!state.hasUpdated) {
|
|
29
|
+
state.hasUpdated = true;
|
|
30
|
+
state.value = target;
|
|
31
|
+
return state;
|
|
32
|
+
}
|
|
33
|
+
dt = Math.max(0, dt);
|
|
34
|
+
const current = state.value;
|
|
35
|
+
const distance = Math.abs(target - current);
|
|
36
|
+
if (distance < epsilon) {
|
|
37
|
+
state.velocity = 0;
|
|
38
|
+
state.previousDistance = 0;
|
|
39
|
+
state.value = target;
|
|
40
|
+
return state;
|
|
41
|
+
}
|
|
42
|
+
const smoothTime = typeof damping === "number" ? damping : distance > state.previousDistance ? damping.into : damping.from;
|
|
43
|
+
state.previousDistance = distance;
|
|
44
|
+
const time = Math.max(1e-4, smoothTime);
|
|
45
|
+
const maxChange = maxSpeed * Math.max(time, dt);
|
|
46
|
+
const change = clamp(current - target, -maxChange, maxChange);
|
|
47
|
+
spring.damp(state, current - change, time, dt);
|
|
48
|
+
if (target - current > 0 === state.value > target) {
|
|
49
|
+
state.value = target;
|
|
50
|
+
state.velocity = 0;
|
|
51
|
+
}
|
|
52
|
+
return state;
|
|
53
|
+
}
|
|
54
|
+
var createVector3State = () => ({
|
|
55
|
+
x: createState(),
|
|
56
|
+
y: createState(),
|
|
57
|
+
z: createState()
|
|
58
|
+
});
|
|
59
|
+
/** Reset all three component dampers. */
|
|
60
|
+
function resetVector3(state) {
|
|
61
|
+
reset(state.x);
|
|
62
|
+
reset(state.y);
|
|
63
|
+
reset(state.z);
|
|
64
|
+
}
|
|
65
|
+
/** Damps the components of `out` toward `target` independently. Mutates and returns `out`. */
|
|
66
|
+
function dampVector3(state, out, target, damping, dt, maxSpeed = Infinity) {
|
|
67
|
+
if (typeof damping === "number" && damping <= 0) return vec3.copy(out, target);
|
|
68
|
+
state.x.value = out[0];
|
|
69
|
+
state.y.value = out[1];
|
|
70
|
+
state.z.value = out[2];
|
|
71
|
+
out[0] = damp(state.x, target[0], damping, dt, maxSpeed).value;
|
|
72
|
+
out[1] = damp(state.y, target[1], damping, dt, maxSpeed).value;
|
|
73
|
+
out[2] = damp(state.z, target[2], damping, dt, maxSpeed).value;
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
var scratchOutInverse = [
|
|
77
|
+
0,
|
|
78
|
+
0,
|
|
79
|
+
0,
|
|
80
|
+
1
|
|
81
|
+
];
|
|
82
|
+
var scratchDelta = [
|
|
83
|
+
0,
|
|
84
|
+
0,
|
|
85
|
+
0,
|
|
86
|
+
1
|
|
87
|
+
];
|
|
88
|
+
var scratchAxis = [
|
|
89
|
+
0,
|
|
90
|
+
0,
|
|
91
|
+
0
|
|
92
|
+
];
|
|
93
|
+
var scratchStep = [
|
|
94
|
+
0,
|
|
95
|
+
0,
|
|
96
|
+
0,
|
|
97
|
+
1
|
|
98
|
+
];
|
|
99
|
+
/** Damps `out` toward `target` along the shortest angular delta. Mutates and returns `out`. */
|
|
100
|
+
function dampQuaternion(state, out, target, damping, dt, maxSpeed = Infinity) {
|
|
101
|
+
if (typeof damping === "number" && damping <= 0) return vec4.copy(out, target);
|
|
102
|
+
quat.conjugate(scratchOutInverse, out);
|
|
103
|
+
quat.multiply(scratchDelta, target, scratchOutInverse);
|
|
104
|
+
if (scratchDelta[3] < 0) vec4.negate(scratchDelta, scratchDelta);
|
|
105
|
+
const angle = 2 * Math.acos(clamp(scratchDelta[3], -1, 1));
|
|
106
|
+
if (angle < 1e-5) {
|
|
107
|
+
state.value = 0;
|
|
108
|
+
damp(state, 0, damping, dt);
|
|
109
|
+
state.velocity = 0;
|
|
110
|
+
return vec4.copy(out, target);
|
|
111
|
+
}
|
|
112
|
+
state.value = 0;
|
|
113
|
+
const dampedAngle = damp(state, angle, damping, dt, maxSpeed).value;
|
|
114
|
+
const halfSin = Math.sin(angle / 2);
|
|
115
|
+
vec3.set(scratchAxis, scratchDelta[0] / halfSin, scratchDelta[1] / halfSin, scratchDelta[2] / halfSin);
|
|
116
|
+
return quat.multiply(out, quat.setAxisAngle(scratchStep, scratchAxis, dampedAngle), out);
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
export { createState, createVector3State, damp, dampQuaternion, dampVector3, damping_exports, reset, resetVector3 };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Vec3 } from 'math';
|
|
2
|
+
import type { Vector3DamperState } from './damping.js';
|
|
3
|
+
/** Velocity tracking state for position extrapolation. */
|
|
4
|
+
export type PredictorState = {
|
|
5
|
+
velocity: Vec3;
|
|
6
|
+
previousPosition: Vec3;
|
|
7
|
+
velocityDamper: Vector3DamperState;
|
|
8
|
+
hasPosition: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare const create: () => PredictorState;
|
|
11
|
+
/** Clear the tracked velocity and position history. */
|
|
12
|
+
export declare function reset(state: PredictorState): void;
|
|
13
|
+
/** Add a position sample and update the tracked velocity. */
|
|
14
|
+
export declare function addPosition(state: PredictorState, position: Vec3, dt: number, smoothing: number): void;
|
|
15
|
+
/** Write the predicted offset `time` seconds ahead into `out`. */
|
|
16
|
+
export declare function predictDelta(out: Vec3, state: PredictorState, time: number): Vec3;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { createVector3State, dampVector3, resetVector3 } from "./damping.js";
|
|
3
|
+
import { vec3 } from "math";
|
|
4
|
+
//#region src/core/damping/predictor.ts
|
|
5
|
+
var predictor_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
addPosition: () => addPosition,
|
|
7
|
+
create: () => create,
|
|
8
|
+
predictDelta: () => predictDelta,
|
|
9
|
+
reset: () => reset
|
|
10
|
+
});
|
|
11
|
+
var create = () => ({
|
|
12
|
+
velocity: [
|
|
13
|
+
0,
|
|
14
|
+
0,
|
|
15
|
+
0
|
|
16
|
+
],
|
|
17
|
+
previousPosition: [
|
|
18
|
+
0,
|
|
19
|
+
0,
|
|
20
|
+
0
|
|
21
|
+
],
|
|
22
|
+
velocityDamper: createVector3State(),
|
|
23
|
+
hasPosition: false
|
|
24
|
+
});
|
|
25
|
+
/** Clear the tracked velocity and position history. */
|
|
26
|
+
function reset(state) {
|
|
27
|
+
vec3.set(state.velocity, 0, 0, 0);
|
|
28
|
+
resetVector3(state.velocityDamper);
|
|
29
|
+
state.hasPosition = false;
|
|
30
|
+
}
|
|
31
|
+
var scratchRawVelocity = [
|
|
32
|
+
0,
|
|
33
|
+
0,
|
|
34
|
+
0
|
|
35
|
+
];
|
|
36
|
+
/** Add a position sample and update the tracked velocity. */
|
|
37
|
+
function addPosition(state, position, dt, smoothing) {
|
|
38
|
+
if (!state.hasPosition) {
|
|
39
|
+
state.hasPosition = true;
|
|
40
|
+
vec3.copy(state.previousPosition, position);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
dt = Math.max(0, dt);
|
|
44
|
+
if (dt > 0) {
|
|
45
|
+
vec3.scale(scratchRawVelocity, vec3.subtract(scratchRawVelocity, position, state.previousPosition), 1 / dt);
|
|
46
|
+
const slowing = vec3.squaredLength(scratchRawVelocity) < vec3.squaredLength(state.velocity);
|
|
47
|
+
dampVector3(state.velocityDamper, state.velocity, scratchRawVelocity, smoothing / (slowing ? 30 : 10), dt);
|
|
48
|
+
}
|
|
49
|
+
vec3.copy(state.previousPosition, position);
|
|
50
|
+
}
|
|
51
|
+
/** Write the predicted offset `time` seconds ahead into `out`. */
|
|
52
|
+
function predictDelta(out, state, time) {
|
|
53
|
+
return vec3.scale(out, state.velocity, time);
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { addPosition, create, predictDelta, predictor_exports, reset };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GroupFramingMode } from '../extension/groupFraming.js';
|
|
2
|
+
export type DebugZone = {
|
|
3
|
+
/** Zone center in normalized screen coordinates. */
|
|
4
|
+
screenPosition: [number, number];
|
|
5
|
+
/** Zone width and height. */
|
|
6
|
+
size: [number, number];
|
|
7
|
+
/** CSS class applied to the zone. */
|
|
8
|
+
className: string;
|
|
9
|
+
};
|
|
10
|
+
/** A composer's hard limit and dead zone as boxes. Both are half-extents around `screenPosition`. */
|
|
11
|
+
export declare function composer(screenPosition: [number, number], deadZone: [number, number], hardLimit: [number, number]): DebugZone[];
|
|
12
|
+
/**
|
|
13
|
+
* Size of group framing's padding boundary on screen, for a group `distance` away. An axis left out by
|
|
14
|
+
* `framingMode` spans the full frame.
|
|
15
|
+
*/
|
|
16
|
+
export declare function groupFramingPaddingBox(out: [number, number], fov: number, aspect: number, distance: number, padding: number, framingMode: GroupFramingMode): [number, number];
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { horizontalHalfFov } from "../extension/groupFraming.js";
|
|
3
|
+
import { clamp, degreesToRadians } from "math";
|
|
4
|
+
//#region src/core/debug/debugZones.ts
|
|
5
|
+
var debugZones_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
composer: () => composer,
|
|
7
|
+
groupFramingPaddingBox: () => groupFramingPaddingBox
|
|
8
|
+
});
|
|
9
|
+
/** A composer's hard limit and dead zone as boxes. Both are half-extents around `screenPosition`. */
|
|
10
|
+
function composer(screenPosition, deadZone, hardLimit) {
|
|
11
|
+
const zones = [];
|
|
12
|
+
if (hardLimit[0] > 0 || hardLimit[1] > 0) zones.push({
|
|
13
|
+
screenPosition,
|
|
14
|
+
size: [hardLimit[0] * 2, hardLimit[1] * 2],
|
|
15
|
+
className: "klipp-debug-hardlimit"
|
|
16
|
+
});
|
|
17
|
+
if (deadZone[0] > 0 || deadZone[1] > 0) zones.push({
|
|
18
|
+
screenPosition,
|
|
19
|
+
size: [deadZone[0] * 2, deadZone[1] * 2],
|
|
20
|
+
className: "klipp-debug-deadzone"
|
|
21
|
+
});
|
|
22
|
+
return zones;
|
|
23
|
+
}
|
|
24
|
+
function paddingEdgeFraction(halfFov, distance, padding) {
|
|
25
|
+
return clamp(1 - padding / (distance * Math.sin(halfFov)), 0, 1);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Size of group framing's padding boundary on screen, for a group `distance` away. An axis left out by
|
|
29
|
+
* `framingMode` spans the full frame.
|
|
30
|
+
*/
|
|
31
|
+
function groupFramingPaddingBox(out, fov, aspect, distance, padding, framingMode) {
|
|
32
|
+
const verticalHalfFov = degreesToRadians(fov) / 2;
|
|
33
|
+
out[0] = framingMode === "vertical" ? 2 : paddingEdgeFraction(horizontalHalfFov(verticalHalfFov, aspect), distance, padding) * 2;
|
|
34
|
+
out[1] = framingMode === "horizontal" ? 2 : paddingEdgeFraction(verticalHalfFov, distance, padding) * 2;
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { composer, debugZones_exports, groupFramingPaddingBox };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CameraState } from '../CameraState.js';
|
|
2
|
+
import type { DampingConstant } from '../damping/damping.js';
|
|
3
|
+
import * as groupFraming from './groupFraming.js';
|
|
4
|
+
import type { GroupFramingFitMode, GroupFramingMode, GroupFramingParams, GroupMember, GroupPositionMode } from './groupFraming.js';
|
|
5
|
+
export type GroupFramingOptions = Partial<GroupFramingParams>;
|
|
6
|
+
/** Keeps a group of members in frame by adjusting distance and view offset. Layers override `readMembers`. */
|
|
7
|
+
export declare class GroupFramingExtension implements GroupFramingParams {
|
|
8
|
+
/** The members, updated by the caller every frame. */
|
|
9
|
+
members: readonly GroupMember[];
|
|
10
|
+
positionMode: GroupPositionMode;
|
|
11
|
+
padding: number;
|
|
12
|
+
viewportWidth: number;
|
|
13
|
+
viewportHeight: number;
|
|
14
|
+
damping: DampingConstant;
|
|
15
|
+
maxSpeed: number;
|
|
16
|
+
screenPosition: [number, number];
|
|
17
|
+
fitMode: GroupFramingFitMode;
|
|
18
|
+
minDistance: number;
|
|
19
|
+
maxDistance: number;
|
|
20
|
+
framingMode: GroupFramingMode;
|
|
21
|
+
readonly state: groupFraming.GroupFramingState;
|
|
22
|
+
constructor(members?: readonly GroupMember[], positionMode?: GroupPositionMode, options?: GroupFramingOptions);
|
|
23
|
+
update: (out: CameraState, dt: number, justActivated: boolean) => boolean;
|
|
24
|
+
/** This frame's members. */
|
|
25
|
+
protected readMembers(): readonly GroupMember[];
|
|
26
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createParams, createState, update } from "./groupFraming.js";
|
|
2
|
+
//#region src/core/extension/GroupFramingExtension.ts
|
|
3
|
+
/** Keeps a group of members in frame by adjusting distance and view offset. Layers override `readMembers`. */
|
|
4
|
+
var GroupFramingExtension = class {
|
|
5
|
+
/** The members, updated by the caller every frame. */
|
|
6
|
+
members;
|
|
7
|
+
positionMode;
|
|
8
|
+
state = createState();
|
|
9
|
+
constructor(members = [], positionMode = "groupCenter", options) {
|
|
10
|
+
this.members = members;
|
|
11
|
+
this.positionMode = positionMode;
|
|
12
|
+
Object.assign(this, createParams(options));
|
|
13
|
+
}
|
|
14
|
+
update = (out, dt, justActivated) => {
|
|
15
|
+
const members = this.readMembers();
|
|
16
|
+
return update(out, this.state, this, members, this.positionMode, dt, justActivated);
|
|
17
|
+
};
|
|
18
|
+
/** This frame's members. */
|
|
19
|
+
readMembers() {
|
|
20
|
+
return this.members;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
//#endregion
|
|
24
|
+
export { GroupFramingExtension };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CameraState } from '../CameraState.js';
|
|
2
|
+
import type { DampingConstant } from '../damping/damping.js';
|
|
3
|
+
import * as lens from './lens.js';
|
|
4
|
+
import type { LensParams } from './lens.js';
|
|
5
|
+
export type LensOptions = Partial<LensParams>;
|
|
6
|
+
/** Overrides lens fields with independent damping. */
|
|
7
|
+
export declare class LensExtension implements LensParams {
|
|
8
|
+
fov?: number;
|
|
9
|
+
near?: number;
|
|
10
|
+
far?: number;
|
|
11
|
+
fovDamping: DampingConstant;
|
|
12
|
+
nearDamping: DampingConstant;
|
|
13
|
+
farDamping: DampingConstant;
|
|
14
|
+
fovMaxSpeed: number;
|
|
15
|
+
nearMaxSpeed: number;
|
|
16
|
+
farMaxSpeed: number;
|
|
17
|
+
readonly state: lens.LensState;
|
|
18
|
+
constructor(options?: LensOptions);
|
|
19
|
+
update: (out: CameraState, dt: number, justActivated: boolean) => boolean;
|
|
20
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createParams, createState, update } from "./lens.js";
|
|
2
|
+
//#region src/core/extension/LensExtension.ts
|
|
3
|
+
/** Overrides lens fields with independent damping. */
|
|
4
|
+
var LensExtension = class {
|
|
5
|
+
state = createState();
|
|
6
|
+
constructor(options) {
|
|
7
|
+
Object.assign(this, createParams(options));
|
|
8
|
+
}
|
|
9
|
+
update = (out, dt, justActivated) => update(out, this.state, this, dt, justActivated);
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { LensExtension };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type Vec3 } from 'math';
|
|
2
|
+
import type { CameraState } from '../CameraState.js';
|
|
3
|
+
import type { TargetExtent } from '../TargetExtent.js';
|
|
4
|
+
import type { DamperState, DampingConstant } from '../damping/damping.js';
|
|
5
|
+
/** A group member. Set `resolved` to `false` to skip it, for example while it isn't loaded yet. */
|
|
6
|
+
export type GroupMember = {
|
|
7
|
+
position: Vec3;
|
|
8
|
+
extent: TargetExtent;
|
|
9
|
+
weight: number;
|
|
10
|
+
resolved: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare const createMember: () => GroupMember;
|
|
13
|
+
/** Strategy used to compute the group's position. */
|
|
14
|
+
export type GroupPositionMode = 'groupCenter' | 'groupAverage';
|
|
15
|
+
/** Fit mode controlling whether the extension can dolly the camera closer. */
|
|
16
|
+
export type GroupFramingFitMode = 'ceiling' | 'rigid';
|
|
17
|
+
/** Which screen dimensions the fit distance has to satisfy. */
|
|
18
|
+
export type GroupFramingMode = 'horizontal' | 'vertical' | 'horizontalAndVertical';
|
|
19
|
+
export type GroupFramingParams = {
|
|
20
|
+
/** Margin kept clear around the group's members, in world units. */
|
|
21
|
+
padding: number;
|
|
22
|
+
/** Viewport width in pixels. */
|
|
23
|
+
viewportWidth: number;
|
|
24
|
+
/** Viewport height in pixels. */
|
|
25
|
+
viewportHeight: number;
|
|
26
|
+
/** Response time for distance and screen composition. */
|
|
27
|
+
damping: DampingConstant;
|
|
28
|
+
/** Maximum damping speed, in world units/sec. */
|
|
29
|
+
maxSpeed: number;
|
|
30
|
+
/** Frustum offset used to compose the group on screen. */
|
|
31
|
+
screenPosition: [number, number];
|
|
32
|
+
/** `'ceiling'` never dollies closer than the Body placed the camera, `'rigid'` always sits at the fit distance. */
|
|
33
|
+
fitMode: GroupFramingFitMode;
|
|
34
|
+
/** Minimum fit distance. */
|
|
35
|
+
minDistance: number;
|
|
36
|
+
/** Maximum fit distance. */
|
|
37
|
+
maxDistance: number;
|
|
38
|
+
/** Which screen dimensions the fit distance has to satisfy. */
|
|
39
|
+
framingMode: GroupFramingMode;
|
|
40
|
+
};
|
|
41
|
+
/** Every setting from `settings`, or its default. */
|
|
42
|
+
export declare const createParams: (settings?: Partial<GroupFramingParams>) => GroupFramingParams;
|
|
43
|
+
export type GroupFramingState = {
|
|
44
|
+
distanceDamper: DamperState;
|
|
45
|
+
screenPositionXDamper: DamperState;
|
|
46
|
+
screenPositionYDamper: DamperState;
|
|
47
|
+
currentDistance: number;
|
|
48
|
+
currentScreenPosition: [number, number];
|
|
49
|
+
};
|
|
50
|
+
export declare const createState: () => GroupFramingState;
|
|
51
|
+
/**
|
|
52
|
+
* Writes the group position to `outPosition` and returns a conservative enclosing radius, or -1 (leaving
|
|
53
|
+
* `outPosition` untouched) when no member is resolved.
|
|
54
|
+
*/
|
|
55
|
+
export declare function computeBounds(outPosition: Vec3, members: readonly GroupMember[], mode: GroupPositionMode): number;
|
|
56
|
+
/** Half the horizontal field of view, in radians, for a vertical half-FOV and aspect ratio. */
|
|
57
|
+
export declare const horizontalHalfFov: (verticalHalfFov: number, aspect: number) => number;
|
|
58
|
+
/**
|
|
59
|
+
* Keeps the group inside the frame by moving `out` along its own view axis and easing `viewOffset` to
|
|
60
|
+
* `screenPosition`. Returns true while still moving.
|
|
61
|
+
*/
|
|
62
|
+
export declare function update(out: CameraState, state: GroupFramingState, params: GroupFramingParams, members: readonly GroupMember[], positionMode: GroupPositionMode, dt: number, justActivated: boolean): boolean;
|