@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.
Files changed (270) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -2
  3. package/dist/_virtual/_rolldown/runtime.js +13 -0
  4. package/dist/core/CameraState.d.ts +32 -0
  5. package/dist/core/CameraState.js +97 -0
  6. package/dist/core/EventDispatcher.d.ts +18 -0
  7. package/dist/core/EventDispatcher.js +28 -0
  8. package/dist/core/Klipp.d.ts +109 -0
  9. package/dist/core/Klipp.js +253 -0
  10. package/dist/core/TargetExtent.d.ts +11 -0
  11. package/dist/core/TargetExtent.js +54 -0
  12. package/dist/core/TargetPose.d.ts +13 -0
  13. package/dist/core/TargetPose.js +21 -0
  14. package/dist/core/VirtualCamera.d.ts +102 -0
  15. package/dist/core/VirtualCamera.js +290 -0
  16. package/dist/core/aim/HardLookAtAim.d.ts +10 -0
  17. package/dist/core/aim/HardLookAtAim.js +19 -0
  18. package/dist/core/aim/PanTiltAim.d.ts +26 -0
  19. package/dist/core/aim/PanTiltAim.js +38 -0
  20. package/dist/core/aim/RotateWithFollowTargetAim.d.ts +19 -0
  21. package/dist/core/aim/RotateWithFollowTargetAim.js +23 -0
  22. package/dist/core/aim/RotationComposerAim.d.ts +27 -0
  23. package/dist/core/aim/RotationComposerAim.js +27 -0
  24. package/dist/core/aim/hardLookAt.d.ts +4 -0
  25. package/dist/core/aim/hardLookAt.js +13 -0
  26. package/dist/core/aim/index.d.ts +11 -0
  27. package/dist/core/aim/lookRotation.d.ts +6 -0
  28. package/dist/core/aim/lookRotation.js +46 -0
  29. package/dist/core/aim/panTilt.d.ts +16 -0
  30. package/dist/core/aim/panTilt.js +121 -0
  31. package/dist/core/aim/rotateWithFollowTarget.d.ts +20 -0
  32. package/dist/core/aim/rotateWithFollowTarget.js +35 -0
  33. package/dist/core/aim/rotationComposer.d.ts +58 -0
  34. package/dist/core/aim/rotationComposer.js +284 -0
  35. package/dist/core/blend/BlendCurves.d.ts +19 -0
  36. package/dist/core/blend/BlendCurves.js +22 -0
  37. package/dist/core/blend/BlendDefinition.d.ts +21 -0
  38. package/dist/core/blend/BlendDefinition.js +9 -0
  39. package/dist/core/blend/BlendDriver.d.ts +23 -0
  40. package/dist/core/blend/BlendDriver.js +42 -0
  41. package/dist/core/blend/BlendHints.d.ts +9 -0
  42. package/dist/core/blend/BlendHints.js +13 -0
  43. package/dist/core/blend/blend.d.ts +41 -0
  44. package/dist/core/blend/blend.js +110 -0
  45. package/dist/core/blend/index.d.ts +6 -0
  46. package/dist/core/blend/lerpCameraState.d.ts +4 -0
  47. package/dist/core/blend/lerpCameraState.js +143 -0
  48. package/dist/core/body/BindingModes.d.ts +9 -0
  49. package/dist/core/body/BindingModes.js +11 -0
  50. package/dist/core/body/FollowBody.d.ts +24 -0
  51. package/dist/core/body/FollowBody.js +26 -0
  52. package/dist/core/body/HardLockToTargetBody.d.ts +17 -0
  53. package/dist/core/body/HardLockToTargetBody.js +20 -0
  54. package/dist/core/body/OrbitFollowBody.d.ts +47 -0
  55. package/dist/core/body/OrbitFollowBody.js +48 -0
  56. package/dist/core/body/PositionComposerBody.d.ts +28 -0
  57. package/dist/core/body/PositionComposerBody.js +27 -0
  58. package/dist/core/body/follow.d.ts +33 -0
  59. package/dist/core/body/follow.js +83 -0
  60. package/dist/core/body/hardLockToTarget.d.ts +17 -0
  61. package/dist/core/body/hardLockToTarget.js +26 -0
  62. package/dist/core/body/index.d.ts +17 -0
  63. package/dist/core/body/orbitFollow.d.ts +76 -0
  64. package/dist/core/body/orbitFollow.js +336 -0
  65. package/dist/core/body/positionComposer.d.ts +56 -0
  66. package/dist/core/body/positionComposer.js +207 -0
  67. package/dist/core/body/safeFromToRotation.d.ts +3 -0
  68. package/dist/core/body/safeFromToRotation.js +39 -0
  69. package/dist/core/body/threeRing.d.ts +28 -0
  70. package/dist/core/body/threeRing.js +100 -0
  71. package/dist/core/body/tracker.d.ts +42 -0
  72. package/dist/core/body/tracker.js +193 -0
  73. package/dist/core/damping/Damper.d.ts +11 -0
  74. package/dist/core/damping/Damper.js +22 -0
  75. package/dist/core/damping/damping.d.ts +30 -0
  76. package/dist/core/damping/damping.js +119 -0
  77. package/dist/core/damping/index.d.ts +5 -0
  78. package/dist/core/damping/predictor.d.ts +16 -0
  79. package/dist/core/damping/predictor.js +56 -0
  80. package/dist/core/debug/debugZones.d.ts +16 -0
  81. package/dist/core/debug/debugZones.js +38 -0
  82. package/dist/core/debug/index.d.ts +2 -0
  83. package/dist/core/extension/GroupFramingExtension.d.ts +26 -0
  84. package/dist/core/extension/GroupFramingExtension.js +24 -0
  85. package/dist/core/extension/LensExtension.d.ts +20 -0
  86. package/dist/core/extension/LensExtension.js +12 -0
  87. package/dist/core/extension/groupFraming.d.ts +62 -0
  88. package/dist/core/extension/groupFraming.js +271 -0
  89. package/dist/core/extension/index.d.ts +6 -0
  90. package/dist/core/extension/lens.d.ts +35 -0
  91. package/dist/core/extension/lens.js +57 -0
  92. package/dist/core/groups/ClearShot.d.ts +32 -0
  93. package/dist/core/groups/MixingCamera.d.ts +20 -0
  94. package/dist/core/groups/Sequencer.d.ts +24 -0
  95. package/dist/core/groups/StateDrivenCamera.d.ts +26 -0
  96. package/dist/core/groups/clearShotState.d.ts +32 -0
  97. package/dist/core/groups/index.d.ts +11 -0
  98. package/dist/core/groups/mixCameraStates.d.ts +13 -0
  99. package/dist/core/groups/sequencerState.d.ts +26 -0
  100. package/dist/core/groups/stateDrivenState.d.ts +28 -0
  101. package/dist/core/impulse/ImpulseField.d.ts +15 -0
  102. package/dist/core/impulse/ImpulseField.js +22 -0
  103. package/dist/core/impulse/ImpulseListenerNoise.d.ts +19 -0
  104. package/dist/core/impulse/ImpulseListenerNoise.js +29 -0
  105. package/dist/core/impulse/impulseListener.d.ts +13 -0
  106. package/dist/core/impulse/impulseListener.js +14 -0
  107. package/dist/core/impulse/impulses.d.ts +54 -0
  108. package/dist/core/impulse/impulses.js +84 -0
  109. package/dist/core/impulse/index.d.ts +6 -0
  110. package/dist/core/index.d.ts +20 -0
  111. package/dist/core/index.js +52 -0
  112. package/dist/core/input/InputAxis.d.ts +29 -0
  113. package/dist/core/input/InputAxis.js +28 -0
  114. package/dist/core/input/InputAxisOwner.d.ts +6 -0
  115. package/dist/core/input/InputAxisOwner.js +4 -0
  116. package/dist/core/input/InputController.d.ts +15 -0
  117. package/dist/core/input/InputController.js +24 -0
  118. package/dist/core/input/axis.d.ts +52 -0
  119. package/dist/core/input/axis.js +89 -0
  120. package/dist/core/input/consumedInput.d.ts +37 -0
  121. package/dist/core/input/consumedInput.js +34 -0
  122. package/dist/core/input/index.d.ts +9 -0
  123. package/dist/core/input/inputMapping.d.ts +46 -0
  124. package/dist/core/input/inputMapping.js +55 -0
  125. package/dist/core/input/shortestWrappedDelta.d.ts +2 -0
  126. package/dist/core/input/shortestWrappedDelta.js +11 -0
  127. package/dist/core/internal.d.ts +16 -0
  128. package/dist/core/internal.js +19 -0
  129. package/dist/core/klippState.d.ts +78 -0
  130. package/dist/core/klippState.js +124 -0
  131. package/dist/core/noise/BasicMultiChannelPerlinNoise.d.ts +21 -0
  132. package/dist/core/noise/BasicMultiChannelPerlinNoise.js +13 -0
  133. package/dist/core/noise/index.d.ts +3 -0
  134. package/dist/core/noise/perlinNoise.d.ts +36 -0
  135. package/dist/core/noise/perlinNoise.js +110 -0
  136. package/dist/core/params.d.ts +2 -0
  137. package/dist/core/params.js +12 -0
  138. package/dist/dom/DebugOverlay.d.ts +11 -0
  139. package/dist/dom/DebugOverlay.js +96 -0
  140. package/dist/dom/InputControllerDom.d.ts +15 -0
  141. package/dist/dom/InputControllerDom.js +31 -0
  142. package/dist/dom/InputSystem.d.ts +40 -0
  143. package/dist/dom/InputSystem.js +113 -0
  144. package/dist/dom/index.d.ts +3 -0
  145. package/dist/dom/index.js +5 -0
  146. package/dist/input-sources/buttonInput.d.ts +15 -0
  147. package/dist/input-sources/buttonInput.js +23 -0
  148. package/dist/input-sources/isInsideInteractiveArea.d.ts +9 -0
  149. package/dist/input-sources/isInsideInteractiveArea.js +11 -0
  150. package/dist/input-sources/mouse.d.ts +47 -0
  151. package/dist/input-sources/mouse.js +171 -0
  152. package/dist/input-sources/safariGesture.d.ts +32 -0
  153. package/dist/input-sources/safariGesture.js +107 -0
  154. package/dist/input-sources/suppressNativeGestures.d.ts +5 -0
  155. package/dist/input-sources/suppressNativeGestures.js +32 -0
  156. package/dist/input-sources/touch.d.ts +47 -0
  157. package/dist/input-sources/touch.js +173 -0
  158. package/dist/input-sources/wheel.d.ts +28 -0
  159. package/dist/input-sources/wheel.js +44 -0
  160. package/dist/react/CameraFrustumHelper.d.ts +13 -0
  161. package/dist/react/CameraFrustumHelper.js +32 -0
  162. package/dist/react/DebugZoneOverlay.d.ts +7 -0
  163. package/dist/react/DebugZoneOverlay.js +23 -0
  164. package/dist/react/Klipp.d.ts +20 -0
  165. package/dist/react/Klipp.js +47 -0
  166. package/dist/react/KlippContext.d.ts +5 -0
  167. package/dist/react/KlippContext.js +11 -0
  168. package/dist/react/VirtualCamera.d.ts +28 -0
  169. package/dist/react/VirtualCamera.js +81 -0
  170. package/dist/react/VirtualCameraContext.d.ts +11 -0
  171. package/dist/react/VirtualCameraContext.js +21 -0
  172. package/dist/react/aim/Aim.d.ts +11 -0
  173. package/dist/react/aim/Aim.js +14 -0
  174. package/dist/react/aim/HardLookAt.d.ts +10 -0
  175. package/dist/react/aim/HardLookAt.js +15 -0
  176. package/dist/react/aim/PanTilt.d.ts +31 -0
  177. package/dist/react/aim/PanTilt.js +38 -0
  178. package/dist/react/aim/RotateWithFollowTarget.d.ts +10 -0
  179. package/dist/react/aim/RotateWithFollowTarget.js +18 -0
  180. package/dist/react/aim/RotationComposer.d.ts +12 -0
  181. package/dist/react/aim/RotationComposer.js +34 -0
  182. package/dist/react/body/Body.d.ts +11 -0
  183. package/dist/react/body/Body.js +14 -0
  184. package/dist/react/body/CameraControls.d.ts +50 -0
  185. package/dist/react/body/CameraControls.js +106 -0
  186. package/dist/react/body/Follow.d.ts +10 -0
  187. package/dist/react/body/Follow.js +20 -0
  188. package/dist/react/body/HardLockToTarget.d.ts +10 -0
  189. package/dist/react/body/HardLockToTarget.js +18 -0
  190. package/dist/react/body/OrbitFollow.d.ts +25 -0
  191. package/dist/react/body/OrbitFollow.js +67 -0
  192. package/dist/react/body/PositionComposer.d.ts +12 -0
  193. package/dist/react/body/PositionComposer.js +32 -0
  194. package/dist/react/body/camera-controls.d.ts +2 -0
  195. package/dist/react/body/camera-controls.js +3 -0
  196. package/dist/react/extension/Extension.d.ts +7 -0
  197. package/dist/react/extension/Extension.js +10 -0
  198. package/dist/react/extension/GroupFraming.d.ts +14 -0
  199. package/dist/react/extension/GroupFraming.js +52 -0
  200. package/dist/react/extension/Lens.d.ts +7 -0
  201. package/dist/react/extension/Lens.js +31 -0
  202. package/dist/react/impulse/ImpulseListener.d.ts +12 -0
  203. package/dist/react/impulse/ImpulseListener.js +33 -0
  204. package/dist/react/index.d.ts +24 -0
  205. package/dist/react/index.js +24 -0
  206. package/dist/react/input/InputAxisOwnerContext.d.ts +3 -0
  207. package/dist/react/input/InputAxisOwnerContext.js +6 -0
  208. package/dist/react/input/InputController.d.ts +53 -0
  209. package/dist/react/input/InputController.js +115 -0
  210. package/dist/react/noise/BasicMultiChannelPerlin.d.ts +7 -0
  211. package/dist/react/noise/BasicMultiChannelPerlin.js +14 -0
  212. package/dist/react/noise/Noise.d.ts +5 -0
  213. package/dist/react/noise/Noise.js +6 -0
  214. package/dist/react/noise/useBasicMultiChannelPerlinNoise.d.ts +4 -0
  215. package/dist/react/noise/useBasicMultiChannelPerlinNoise.js +21 -0
  216. package/dist/react/useCameraTransitionEvent.d.ts +12 -0
  217. package/dist/react/useCameraTransitionEvent.js +14 -0
  218. package/dist/three/CameraFrustumHelperThree.d.ts +11 -0
  219. package/dist/three/CameraFrustumHelperThree.js +44 -0
  220. package/dist/three/KlippThree.d.ts +18 -0
  221. package/dist/three/KlippThree.js +50 -0
  222. package/dist/three/VirtualCameraThree.d.ts +35 -0
  223. package/dist/three/VirtualCameraThree.js +108 -0
  224. package/dist/three/aim/HardLookAtAimThree.d.ts +10 -0
  225. package/dist/three/aim/HardLookAtAimThree.js +14 -0
  226. package/dist/three/aim/PanTiltAimThree.d.ts +10 -0
  227. package/dist/three/aim/PanTiltAimThree.js +15 -0
  228. package/dist/three/aim/RotateWithFollowTargetAimThree.d.ts +11 -0
  229. package/dist/three/aim/RotateWithFollowTargetAimThree.js +15 -0
  230. package/dist/three/aim/RotationComposerAimThree.d.ts +26 -0
  231. package/dist/three/aim/RotationComposerAimThree.js +35 -0
  232. package/dist/three/body/CameraControlsBodyThree.d.ts +30 -0
  233. package/dist/three/body/CameraControlsBodyThree.js +54 -0
  234. package/dist/three/body/FollowBodyThree.d.ts +16 -0
  235. package/dist/three/body/FollowBodyThree.js +23 -0
  236. package/dist/three/body/HardLockToTargetBodyThree.d.ts +11 -0
  237. package/dist/three/body/HardLockToTargetBodyThree.js +14 -0
  238. package/dist/three/body/OrbitFollowBodyThree.d.ts +16 -0
  239. package/dist/three/body/OrbitFollowBodyThree.js +23 -0
  240. package/dist/three/body/OrbitFollowHelperThree.d.ts +23 -0
  241. package/dist/three/body/OrbitFollowHelperThree.js +85 -0
  242. package/dist/three/body/PositionComposerBodyThree.d.ts +24 -0
  243. package/dist/three/body/PositionComposerBodyThree.js +31 -0
  244. package/dist/three/camera.d.ts +10 -0
  245. package/dist/three/camera.js +39 -0
  246. package/dist/three/damping/Predictor.d.ts +12 -0
  247. package/dist/three/damping/Predictor.js +30 -0
  248. package/dist/three/damping/QuaternionDamper.d.ts +10 -0
  249. package/dist/three/damping/QuaternionDamper.js +28 -0
  250. package/dist/three/damping/Vector3Damper.d.ts +10 -0
  251. package/dist/three/damping/Vector3Damper.js +26 -0
  252. package/dist/three/extension/GroupFramingExtensionThree.d.ts +13 -0
  253. package/dist/three/extension/GroupFramingExtensionThree.js +23 -0
  254. package/dist/three/extension/TargetGroup.d.ts +32 -0
  255. package/dist/three/extension/TargetGroup.js +53 -0
  256. package/dist/three/index.d.ts +24 -0
  257. package/dist/three/index.js +25 -0
  258. package/dist/three/noise/BasicMultiChannelPerlinNoiseThree.d.ts +16 -0
  259. package/dist/three/noise/BasicMultiChannelPerlinNoiseThree.js +17 -0
  260. package/dist/three/readTargetExtent.d.ts +9 -0
  261. package/dist/three/readTargetExtent.js +25 -0
  262. package/dist/three/readTargetPose.d.ts +8 -0
  263. package/dist/three/readTargetPose.js +21 -0
  264. package/dist/three/resolve/Target.d.ts +17 -0
  265. package/dist/three/resolve/Target.js +62 -0
  266. package/dist/three/resolve/TargetRegistry.d.ts +27 -0
  267. package/dist/three/resolve/TargetRegistry.js +78 -0
  268. package/dist/three/resolve/resolveVector3.d.ts +12 -0
  269. package/dist/three/resolve/resolveVector3.js +29 -0
  270. package/package.json +120 -4
@@ -0,0 +1,56 @@
1
+ import { type Vec3 } from 'math';
2
+ import type { CameraState } from '../CameraState.js';
3
+ import type { TargetPose } from '../TargetPose.js';
4
+ import type { DamperState, DampingConstant, Vector3DamperState } from '../damping/damping.js';
5
+ import type { PredictorState } from '../damping/predictor.js';
6
+ export type PositionComposerParams = {
7
+ /** Desired distance from the camera to the target. */
8
+ cameraDistance: number;
9
+ /** Where the target should land on screen: `[x, y]`, `0` = center, `±1` = edge. */
10
+ screenPosition: [number, number];
11
+ /** Viewport width divided by height. */
12
+ aspect: number;
13
+ /** Allowed target drift from `screenPosition` before the camera shifts laterally. */
14
+ deadZone: [number, number];
15
+ /** Response time for dolly and lateral composition. */
16
+ damping: DampingConstant;
17
+ /** Maximum allowed target drift, enforced immediately. */
18
+ hardLimit: [number, number];
19
+ /** Allowed target depth drift before the camera dollies. */
20
+ depthDeadZone: number;
21
+ /** Maximum damping speed for both stages, in world units/sec. */
22
+ maxSpeed: number;
23
+ /** Seconds to extrapolate the target's tracked position ahead by. */
24
+ lookaheadTime: number;
25
+ /** Smooth-time budget (seconds) for the velocity estimate driving `lookaheadTime`. */
26
+ lookaheadSmoothing: number;
27
+ /** Whether lookahead ignores vertical movement. */
28
+ lookaheadIgnoreY: boolean;
29
+ };
30
+ /** Every setting from `settings`, or its default. */
31
+ export declare const createParams: (settings?: Partial<PositionComposerParams>) => PositionComposerParams;
32
+ export type PositionComposerState = {
33
+ damper: Vector3DamperState;
34
+ depthDamper: DamperState;
35
+ predictor: PredictorState;
36
+ primed: boolean;
37
+ /** Activation seen while the target was unresolved, applied on the first frame that has one. */
38
+ activationPending: boolean;
39
+ /** Whether that pending activation was primed. */
40
+ activationPrimed: boolean;
41
+ /** Last desired lateral position, kept while the target stays inside the dead zone. */
42
+ lastActiveDesiredPosition: Vec3;
43
+ hasActiveDesiredPosition: boolean;
44
+ };
45
+ export declare const createState: () => PositionComposerState;
46
+ /** Only extents with a dead zone or hard limit are read, so callers can skip resolving them otherwise. */
47
+ export declare const needsExtent: (params: PositionComposerParams) => boolean;
48
+ /**
49
+ * Positions `out` using depth and screen-space composition around the target and its `extent`. A `null`
50
+ * target leaves `out` as is.
51
+ */
52
+ export declare function update(out: CameraState, state: PositionComposerState, params: PositionComposerParams, targetPose: TargetPose | null, dt: number, justActivated: boolean): void;
53
+ /** Restart the lookahead history, for when the target switches to a different object. */
54
+ export declare function retarget(state: PositionComposerState): void;
55
+ /** Start the next activation from `position` instead of snapping to the target. */
56
+ export declare function prime(state: PositionComposerState, params: PositionComposerParams, position: Vec3): void;
@@ -0,0 +1,207 @@
1
+ import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
2
+ import { createState as createState$1, createVector3State, damp, dampVector3, reset, resetVector3 } from "../damping/damping.js";
3
+ import { project } from "../TargetExtent.js";
4
+ import { withDefaults } from "../params.js";
5
+ import { addPosition, create, predictDelta, reset as reset$1 } from "../damping/predictor.js";
6
+ import { clamp, degreesToRadians, vec3 } from "math";
7
+ //#region src/core/body/positionComposer.ts
8
+ var positionComposer_exports = /* @__PURE__ */ __exportAll({
9
+ createParams: () => createParams,
10
+ createState: () => createState,
11
+ needsExtent: () => needsExtent,
12
+ prime: () => prime,
13
+ retarget: () => retarget,
14
+ update: () => update
15
+ });
16
+ /** Every setting from `settings`, or its default. */
17
+ var createParams = (settings) => withDefaults({
18
+ cameraDistance: 10,
19
+ screenPosition: [0, 0],
20
+ aspect: 1,
21
+ deadZone: [0, 0],
22
+ damping: 0,
23
+ hardLimit: [0, 0],
24
+ depthDeadZone: 0,
25
+ maxSpeed: Infinity,
26
+ lookaheadTime: 0,
27
+ lookaheadSmoothing: 1,
28
+ lookaheadIgnoreY: false
29
+ }, settings);
30
+ var createState = () => ({
31
+ damper: createVector3State(),
32
+ depthDamper: createState$1(),
33
+ predictor: create(),
34
+ primed: false,
35
+ activationPending: false,
36
+ activationPrimed: false,
37
+ lastActiveDesiredPosition: [
38
+ 0,
39
+ 0,
40
+ 0
41
+ ],
42
+ hasActiveDesiredPosition: false
43
+ });
44
+ /** Only extents with a dead zone or hard limit are read, so callers can skip resolving them otherwise. */
45
+ var needsExtent = (params) => params.deadZone[0] > 0 || params.deadZone[1] > 0 || params.hardLimit[0] > 0 || params.hardLimit[1] > 0;
46
+ var scratchTarget = [
47
+ 0,
48
+ 0,
49
+ 0
50
+ ];
51
+ var scratchLookaheadDelta = [
52
+ 0,
53
+ 0,
54
+ 0
55
+ ];
56
+ var scratchForward = [
57
+ 0,
58
+ 0,
59
+ 0
60
+ ];
61
+ var scratchRight = [
62
+ 0,
63
+ 0,
64
+ 0
65
+ ];
66
+ var scratchUp = [
67
+ 0,
68
+ 0,
69
+ 0
70
+ ];
71
+ var scratchRelative = [
72
+ 0,
73
+ 0,
74
+ 0
75
+ ];
76
+ var scratchDesired = [
77
+ 0,
78
+ 0,
79
+ 0
80
+ ];
81
+ var scratchExtents = [0, 0];
82
+ var forwardAxis = [
83
+ 0,
84
+ 0,
85
+ -1
86
+ ];
87
+ var rightAxis = [
88
+ 1,
89
+ 0,
90
+ 0
91
+ ];
92
+ var upAxis = [
93
+ 0,
94
+ 1,
95
+ 0
96
+ ];
97
+ /**
98
+ * Positions `out` using depth and screen-space composition around the target and its `extent`. A `null`
99
+ * target leaves `out` as is.
100
+ */
101
+ function update(out, state, params, targetPose, dt, justActivated) {
102
+ if (justActivated) {
103
+ state.activationPending = true;
104
+ state.activationPrimed = state.primed;
105
+ state.primed = false;
106
+ }
107
+ if (!targetPose) return;
108
+ const activating = state.activationPending;
109
+ const skipReset = activating && state.activationPrimed;
110
+ state.activationPending = false;
111
+ const { extent } = targetPose;
112
+ const target = vec3.copy(scratchTarget, targetPose.position);
113
+ if (activating) reset$1(state.predictor);
114
+ addPosition(state.predictor, target, dt, params.lookaheadSmoothing);
115
+ if (params.lookaheadTime > 0) {
116
+ predictDelta(scratchLookaheadDelta, state.predictor, params.lookaheadTime);
117
+ if (params.lookaheadIgnoreY) scratchLookaheadDelta[1] = 0;
118
+ vec3.add(target, target, scratchLookaheadDelta);
119
+ }
120
+ vec3.copy(out.target, target);
121
+ out.hasTarget = true;
122
+ const position = out.position;
123
+ vec3.transformQuat(scratchForward, forwardAxis, out.quaternion);
124
+ vec3.transformQuat(scratchRight, rightAxis, out.quaternion);
125
+ vec3.transformQuat(scratchUp, upAxis, out.quaternion);
126
+ vec3.subtract(scratchRelative, target, position);
127
+ const currentDepth = vec3.dot(scratchRelative, scratchForward);
128
+ let desiredDepth = params.cameraDistance;
129
+ let insideDepthDeadZone = false;
130
+ if (!activating && params.depthDeadZone > 0) {
131
+ const depthError = currentDepth - params.cameraDistance;
132
+ insideDepthDeadZone = Math.abs(depthError) <= params.depthDeadZone;
133
+ if (!insideDepthDeadZone) desiredDepth = params.cameraDistance + clamp(depthError, -params.depthDeadZone, params.depthDeadZone);
134
+ }
135
+ if (!insideDepthDeadZone) {
136
+ if (activating && !skipReset) reset(state.depthDamper);
137
+ const instant = typeof params.damping === "number" && params.damping <= 0;
138
+ state.depthDamper.value = currentDepth;
139
+ const dampedDepth = instant ? desiredDepth : damp(state.depthDamper, desiredDepth, params.damping, dt, params.maxSpeed).value;
140
+ vec3.scaleAndAdd(position, position, scratchForward, currentDepth - dampedDepth);
141
+ }
142
+ vec3.subtract(scratchRelative, target, position);
143
+ const halfHeight = params.cameraDistance * Math.tan(degreesToRadians(out.fov) / 2);
144
+ const halfWidth = halfHeight * params.aspect;
145
+ project(scratchExtents, extent, scratchRight, scratchUp);
146
+ const extentX = scratchExtents[0] / halfWidth;
147
+ const extentY = scratchExtents[1] / halfHeight;
148
+ const currentRight = vec3.dot(scratchRelative, scratchRight);
149
+ const currentUp = vec3.dot(scratchRelative, scratchUp);
150
+ let desiredScreenX = params.screenPosition[0];
151
+ let desiredScreenY = params.screenPosition[1];
152
+ let insideDeadZone = false;
153
+ if (!activating && (params.deadZone[0] > 0 || params.deadZone[1] > 0)) {
154
+ const halfDeadWidth = params.deadZone[0];
155
+ const halfDeadHeight = params.deadZone[1];
156
+ const deadExtentX = Math.min(extentX, halfDeadWidth);
157
+ const deadExtentY = Math.min(extentY, halfDeadHeight);
158
+ const errorX = currentRight / halfWidth - params.screenPosition[0];
159
+ const errorY = currentUp / halfHeight - params.screenPosition[1];
160
+ const edgeErrorX = errorX + Math.sign(errorX) * deadExtentX;
161
+ const edgeErrorY = errorY + Math.sign(errorY) * deadExtentY;
162
+ insideDeadZone = Math.abs(edgeErrorX) <= halfDeadWidth && Math.abs(edgeErrorY) <= halfDeadHeight;
163
+ if (!insideDeadZone) {
164
+ desiredScreenX = params.screenPosition[0] + clamp(edgeErrorX, -halfDeadWidth, halfDeadWidth) - Math.sign(errorX) * deadExtentX;
165
+ desiredScreenY = params.screenPosition[1] + clamp(edgeErrorY, -halfDeadHeight, halfDeadHeight) - Math.sign(errorY) * deadExtentY;
166
+ }
167
+ }
168
+ if (!insideDeadZone) {
169
+ vec3.scaleAndAdd(scratchDesired, position, scratchRight, currentRight - desiredScreenX * halfWidth);
170
+ vec3.scaleAndAdd(scratchDesired, scratchDesired, scratchUp, currentUp - desiredScreenY * halfHeight);
171
+ vec3.copy(state.lastActiveDesiredPosition, scratchDesired);
172
+ state.hasActiveDesiredPosition = true;
173
+ } else if (state.hasActiveDesiredPosition) vec3.copy(scratchDesired, state.lastActiveDesiredPosition);
174
+ else vec3.copy(scratchDesired, position);
175
+ if (activating && !skipReset) resetVector3(state.damper);
176
+ dampVector3(state.damper, position, scratchDesired, params.damping, dt, params.maxSpeed);
177
+ if (params.hardLimit[0] <= 0 && params.hardLimit[1] <= 0) return;
178
+ vec3.subtract(scratchRelative, target, position);
179
+ const afterRight = vec3.dot(scratchRelative, scratchRight);
180
+ const afterUp = vec3.dot(scratchRelative, scratchUp);
181
+ const halfLimitWidth = params.hardLimit[0];
182
+ const halfLimitHeight = params.hardLimit[1];
183
+ const limitExtentX = Math.min(extentX, halfLimitWidth);
184
+ const limitExtentY = Math.min(extentY, halfLimitHeight);
185
+ const limitErrorX = afterRight / halfWidth - params.screenPosition[0];
186
+ const limitErrorY = afterUp / halfHeight - params.screenPosition[1];
187
+ const limitEdgeErrorX = limitErrorX + Math.sign(limitErrorX) * limitExtentX;
188
+ const limitEdgeErrorY = limitErrorY + Math.sign(limitErrorY) * limitExtentY;
189
+ if (Math.abs(limitEdgeErrorX) <= halfLimitWidth && Math.abs(limitEdgeErrorY) <= halfLimitHeight) return;
190
+ const clampedX = params.screenPosition[0] + clamp(limitEdgeErrorX, -halfLimitWidth, halfLimitWidth) - Math.sign(limitErrorX) * limitExtentX;
191
+ const clampedY = params.screenPosition[1] + clamp(limitEdgeErrorY, -halfLimitHeight, halfLimitHeight) - Math.sign(limitErrorY) * limitExtentY;
192
+ vec3.scaleAndAdd(position, position, scratchRight, afterRight - clampedX * halfWidth);
193
+ vec3.scaleAndAdd(position, position, scratchUp, afterUp - clampedY * halfHeight);
194
+ }
195
+ /** Restart the lookahead history, for when the target switches to a different object. */
196
+ function retarget(state) {
197
+ reset$1(state.predictor);
198
+ }
199
+ /** Start the next activation from `position` instead of snapping to the target. */
200
+ function prime(state, params, position) {
201
+ dampVector3(state.damper, position, position, params.damping, 0);
202
+ state.depthDamper.value = 0;
203
+ damp(state.depthDamper, 0, params.damping, 0);
204
+ state.primed = true;
205
+ }
206
+ //#endregion
207
+ export { createParams, createState, needsExtent, positionComposer_exports, prime, retarget, update };
@@ -0,0 +1,3 @@
1
+ import { type Quat, type Vec3 } from 'math';
2
+ /** Rotation from `from` to `to` as a turn around `up` followed by a pitch, so it never adds roll. */
3
+ export declare function safeFromToRotation(out: Quat, from: Vec3, to: Vec3, up: Vec3): Quat;
@@ -0,0 +1,39 @@
1
+ import { quat, vec3 } from "math";
2
+ //#region src/core/body/safeFromToRotation.ts
3
+ var scratchProjectedFrom = [
4
+ 0,
5
+ 0,
6
+ 0
7
+ ];
8
+ var scratchProjectedTo = [
9
+ 0,
10
+ 0,
11
+ 0
12
+ ];
13
+ var scratchAxis = [
14
+ 0,
15
+ 0,
16
+ 0
17
+ ];
18
+ var scratchPitch = [
19
+ 0,
20
+ 0,
21
+ 0,
22
+ 1
23
+ ];
24
+ /** Rotation from `from` to `to` as a turn around `up` followed by a pitch, so it never adds roll. */
25
+ function safeFromToRotation(out, from, to, up) {
26
+ vec3.scaleAndAdd(scratchProjectedFrom, from, up, -vec3.dot(from, up));
27
+ vec3.scaleAndAdd(scratchProjectedTo, to, up, -vec3.dot(to, up));
28
+ if (vec3.squaredLength(scratchProjectedFrom) < 1e-10 || vec3.squaredLength(scratchProjectedTo) < 1e-10) {
29
+ vec3.cross(scratchAxis, from, to);
30
+ if (vec3.squaredLength(scratchAxis) < 1e-10) vec3.copy(scratchAxis, up);
31
+ return quat.setAxisAngle(out, vec3.normalize(scratchAxis, scratchAxis), vec3.angle(from, to));
32
+ }
33
+ vec3.normalize(scratchAxis, vec3.cross(scratchAxis, up, from));
34
+ quat.setAxisAngle(scratchPitch, scratchAxis, vec3.angle(to, up) - vec3.angle(from, up));
35
+ quat.setAxisAngle(out, up, vec3.signedAngle(scratchProjectedFrom, scratchProjectedTo, up));
36
+ return quat.multiply(out, out, scratchPitch);
37
+ }
38
+ //#endregion
39
+ export { safeFromToRotation };
@@ -0,0 +1,28 @@
1
+ import { type Vec3 } from 'math';
2
+ /** A horizontal ring around the target. */
3
+ export type Orbit = {
4
+ /** Horizontal distance from the target. */
5
+ radius: number;
6
+ /** Height above the target. */
7
+ height: number;
8
+ };
9
+ export type Orbits = {
10
+ top: Orbit;
11
+ center: Orbit;
12
+ bottom: Orbit;
13
+ };
14
+ /** A smooth curve through the rings, as `[height, radius]` knots with Bezier control points between them. */
15
+ export type ThreeRingState = {
16
+ /** An extrapolated end, bottom, center, top and another extrapolated end. */
17
+ knots: number[];
18
+ ctrl1: number[];
19
+ ctrl2: number[];
20
+ /** Settings the curve was built for. */
21
+ builtFor: number[];
22
+ };
23
+ export declare const createState: () => ThreeRingState;
24
+ /**
25
+ * Writes the point of the curve at `t` to `out` as `[0, height, radius]`: `0` is the bottom ring, `0.5` the center
26
+ * ring and `1` the top ring. Rebuilds the curve only when the rings or the curvature changed.
27
+ */
28
+ export declare function point(out: Vec3, state: ThreeRingState, orbits: Orbits, splineCurvature: number, t: number): Vec3;
@@ -0,0 +1,100 @@
1
+ import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
2
+ import { clamp } from "math";
3
+ //#region src/core/body/threeRing.ts
4
+ var threeRing_exports = /* @__PURE__ */ __exportAll({
5
+ createState: () => createState,
6
+ point: () => point
7
+ });
8
+ var knotCount = 5;
9
+ var createState = () => ({
10
+ knots: new Array(10).fill(0),
11
+ ctrl1: new Array(10).fill(0),
12
+ ctrl2: new Array(10).fill(0),
13
+ builtFor: new Array(7).fill(NaN)
14
+ });
15
+ function isBuiltFor(state, orbits, splineCurvature) {
16
+ const built = state.builtFor;
17
+ return built[0] === orbits.bottom.height && built[1] === orbits.bottom.radius && built[2] === orbits.center.height && built[3] === orbits.center.radius && built[4] === orbits.top.height && built[5] === orbits.top.radius && built[6] === splineCurvature;
18
+ }
19
+ function setKnot(knots, index, height, radius) {
20
+ knots[index * 2] = height;
21
+ knots[index * 2 + 1] = radius;
22
+ }
23
+ var a = new Array(knotCount).fill(0);
24
+ var b = new Array(knotCount).fill(0);
25
+ var c = new Array(knotCount).fill(0);
26
+ var r = new Array(knotCount).fill(0);
27
+ function computeControlPoints({ knots, ctrl1, ctrl2 }) {
28
+ const n = 4;
29
+ for (let axis = 0; axis < 2; axis++) {
30
+ const k = (i) => knots[i * 2 + axis];
31
+ a[0] = 0;
32
+ b[0] = 2;
33
+ c[0] = 1;
34
+ r[0] = k(0) + 2 * k(1);
35
+ for (let i = 1; i < 3; i++) {
36
+ a[i] = 1;
37
+ b[i] = 4;
38
+ c[i] = 1;
39
+ r[i] = 4 * k(i) + 2 * k(i + 1);
40
+ }
41
+ a[3] = 2;
42
+ b[3] = 7;
43
+ c[3] = 0;
44
+ r[3] = 8 * k(3) + k(n);
45
+ for (let i = 1; i < n; i++) {
46
+ const m = a[i] / b[i - 1];
47
+ b[i] -= m * c[i - 1];
48
+ r[i] -= m * r[i - 1];
49
+ }
50
+ ctrl1[6 + axis] = r[3] / b[3];
51
+ for (let i = 2; i >= 0; i--) ctrl1[i * 2 + axis] = (r[i] - c[i] * ctrl1[(i + 1) * 2 + axis]) / b[i];
52
+ for (let i = 0; i < 3; i++) ctrl2[i * 2 + axis] = 2 * k(i + 1) - ctrl1[(i + 1) * 2 + axis];
53
+ ctrl2[6 + axis] = .5 * (k(n) + ctrl1[6 + axis]);
54
+ }
55
+ }
56
+ function build(state, orbits, splineCurvature) {
57
+ const { bottom, center, top } = orbits;
58
+ const { knots, builtFor } = state;
59
+ setKnot(knots, 1, bottom.height, bottom.radius);
60
+ setKnot(knots, 2, center.height, center.radius);
61
+ setKnot(knots, 3, top.height, top.radius);
62
+ const keep = 1 - clamp(splineCurvature, 0, 1);
63
+ setKnot(knots, 0, keep * (1.5 * bottom.height - .5 * center.height), keep * (1.5 * bottom.radius - .5 * center.radius));
64
+ setKnot(knots, 4, keep * (1.5 * top.height - .5 * center.height), keep * (1.5 * top.radius - .5 * center.radius));
65
+ computeControlPoints(state);
66
+ builtFor[0] = bottom.height;
67
+ builtFor[1] = bottom.radius;
68
+ builtFor[2] = center.height;
69
+ builtFor[3] = center.radius;
70
+ builtFor[4] = top.height;
71
+ builtFor[5] = top.radius;
72
+ builtFor[6] = splineCurvature;
73
+ }
74
+ /**
75
+ * Writes the point of the curve at `t` to `out` as `[0, height, radius]`: `0` is the bottom ring, `0.5` the center
76
+ * ring and `1` the top ring. Rebuilds the curve only when the rings or the curvature changed.
77
+ */
78
+ function point(out, state, orbits, splineCurvature, t) {
79
+ if (!isBuiltFor(state, orbits, splineCurvature)) build(state, orbits, splineCurvature);
80
+ const { knots, ctrl1, ctrl2 } = state;
81
+ let s = clamp(t, 0, 1) * 2;
82
+ let segment = 1;
83
+ if (s > 1) {
84
+ s -= 1;
85
+ segment = 2;
86
+ }
87
+ const d = 1 - s;
88
+ const w0 = d * d * d;
89
+ const w1 = 3 * d * d * s;
90
+ const w2 = 3 * d * s * s;
91
+ const w3 = s * s * s;
92
+ const i = segment * 2;
93
+ const j = (segment + 1) * 2;
94
+ out[0] = 0;
95
+ out[1] = w0 * knots[i] + w1 * ctrl1[i] + w2 * ctrl2[i] + w3 * knots[j];
96
+ out[2] = w0 * knots[i + 1] + w1 * ctrl1[i + 1] + w2 * ctrl2[i + 1] + w3 * knots[j + 1];
97
+ return out;
98
+ }
99
+ //#endregion
100
+ export { createState, point, threeRing_exports };
@@ -0,0 +1,42 @@
1
+ import { type Quat, type Vec3 } from 'math';
2
+ import type { TargetPose } from '../TargetPose.js';
3
+ import type { DamperState, DampingConstant, Vector3DamperState } from '../damping/damping.js';
4
+ import { type BindingMode } from './BindingModes.js';
5
+ export type TrackerParams = {
6
+ /** Rotation frame of the camera offset and the target offset. */
7
+ bindingMode: BindingMode;
8
+ /** Response time for following the target position. */
9
+ damping: DampingConstant;
10
+ /** Response time for turning with the target, for every `bindingMode` but `worldSpace`. */
11
+ rotationDamping: DampingConstant;
12
+ /** Maximum damping speed, in world units/sec. */
13
+ maxSpeed: number;
14
+ };
15
+ export type TrackerState = {
16
+ /** Damped target position, the point the camera offset is added to. */
17
+ trackedPoint: Vec3;
18
+ previousOffset: Vec3;
19
+ hasPrevious: boolean;
20
+ damper: Vector3DamperState;
21
+ /** Damped `bindingMode` rotation, the frame of the offsets. */
22
+ orientation: Quat;
23
+ rotationDamper: DamperState;
24
+ /** Target rotation captured on entering `lockToTargetOnAssign`, valid while `assigned`. */
25
+ assignedRotation: Quat;
26
+ assigned: boolean;
27
+ };
28
+ export declare const createState: () => TrackerState;
29
+ /** Makes the next `trackTarget` snap to the target. */
30
+ export declare function reset(state: TrackerState): void;
31
+ /** Makes the next `trackTarget` ease from `point` and `orientation` instead of snapping to the target. */
32
+ export declare function prime(state: TrackerState, point: Vec3, offset: Vec3, orientation: Quat): void;
33
+ /** Whether `referenceOrientation` will read `target.rotation` this frame. */
34
+ export declare const needsTargetRotation: (state: Pick<TrackerState, 'assigned'>, bindingMode: BindingMode) => boolean;
35
+ /** The rotation `bindingMode` applies to offsets around `target`. Captures it on entering `lockToTargetOnAssign`. */
36
+ export declare function referenceOrientation(out: Quat, state: Pick<TrackerState, 'assignedRotation' | 'assigned'>, bindingMode: BindingMode, target: TargetPose): Quat;
37
+ /**
38
+ * Damps the tracked point toward the target position plus `targetOffset`, per axis of the camera `offset`'s frame.
39
+ * When `offset` changes, the tracked point turns with it around the target, so moving the camera is never damped.
40
+ * Writes the tracked point to `out` and the reference orientation to `outOrientation`.
41
+ */
42
+ export declare function trackTarget(out: Vec3, outOrientation: Quat, state: TrackerState, params: TrackerParams, target: TargetPose, offset: Vec3, targetOffset: Vec3, dt: number): Vec3;
@@ -0,0 +1,193 @@
1
+ import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
2
+ import { createState as createState$1, createVector3State, damp, dampQuaternion, dampVector3, reset as reset$1, resetVector3 } from "../damping/damping.js";
3
+ import { BindingModes } from "./BindingModes.js";
4
+ import { safeFromToRotation } from "./safeFromToRotation.js";
5
+ import { mat4, quat, vec3 } from "math";
6
+ //#region src/core/body/tracker.ts
7
+ var tracker_exports = /* @__PURE__ */ __exportAll({
8
+ createState: () => createState,
9
+ needsTargetRotation: () => needsTargetRotation,
10
+ prime: () => prime,
11
+ referenceOrientation: () => referenceOrientation,
12
+ reset: () => reset,
13
+ trackTarget: () => trackTarget
14
+ });
15
+ var createState = () => ({
16
+ trackedPoint: [
17
+ 0,
18
+ 0,
19
+ 0
20
+ ],
21
+ previousOffset: [
22
+ 0,
23
+ 0,
24
+ 0
25
+ ],
26
+ hasPrevious: false,
27
+ damper: createVector3State(),
28
+ orientation: [
29
+ 0,
30
+ 0,
31
+ 0,
32
+ 1
33
+ ],
34
+ rotationDamper: createState$1(),
35
+ assignedRotation: [
36
+ 0,
37
+ 0,
38
+ 0,
39
+ 1
40
+ ],
41
+ assigned: false
42
+ });
43
+ /** Makes the next `trackTarget` snap to the target. */
44
+ function reset(state) {
45
+ state.hasPrevious = false;
46
+ resetVector3(state.damper);
47
+ reset$1(state.rotationDamper);
48
+ }
49
+ function start(damper) {
50
+ damp(damper, damper.value, 1, 0);
51
+ }
52
+ /** Makes the next `trackTarget` ease from `point` and `orientation` instead of snapping to the target. */
53
+ function prime(state, point, offset, orientation) {
54
+ reset(state);
55
+ vec3.copy(state.trackedPoint, point);
56
+ vec3.copy(state.previousOffset, offset);
57
+ quat.copy(state.orientation, orientation);
58
+ state.hasPrevious = true;
59
+ start(state.damper.x);
60
+ start(state.damper.y);
61
+ start(state.damper.z);
62
+ start(state.rotationDamper);
63
+ }
64
+ /** Whether `referenceOrientation` will read `target.rotation` this frame. */
65
+ var needsTargetRotation = (state, bindingMode) => bindingMode !== BindingModes.worldSpace && !(bindingMode === BindingModes.lockToTargetOnAssign && state.assigned);
66
+ var worldUp = [
67
+ 0,
68
+ 1,
69
+ 0
70
+ ];
71
+ var forwardAxis = [
72
+ 0,
73
+ 0,
74
+ -1
75
+ ];
76
+ var origin = [
77
+ 0,
78
+ 0,
79
+ 0
80
+ ];
81
+ var scratchForward = [
82
+ 0,
83
+ 0,
84
+ 0
85
+ ];
86
+ var scratchLookMatrix = mat4.create();
87
+ /** The rotation `bindingMode` applies to offsets around `target`. Captures it on entering `lockToTargetOnAssign`. */
88
+ function referenceOrientation(out, state, bindingMode, target) {
89
+ if (bindingMode !== BindingModes.lockToTargetOnAssign) state.assigned = false;
90
+ if (bindingMode === BindingModes.worldSpace) return quat.identity(out);
91
+ if (bindingMode === BindingModes.lockToTargetOnAssign) {
92
+ if (!state.assigned) {
93
+ state.assigned = true;
94
+ if (target.hasRotation) quat.copy(state.assignedRotation, target.rotation);
95
+ else quat.identity(state.assignedRotation);
96
+ }
97
+ return quat.copy(out, state.assignedRotation);
98
+ }
99
+ if (!target.hasRotation) return quat.identity(out);
100
+ quat.copy(out, target.rotation);
101
+ if (bindingMode === BindingModes.lockToTarget) return out;
102
+ vec3.transformQuat(scratchForward, forwardAxis, out);
103
+ if (bindingMode === BindingModes.lockToTargetWithWorldUp) scratchForward[1] = 0;
104
+ if (vec3.squaredLength(scratchForward) < 1e-10) return out;
105
+ vec3.normalize(scratchForward, scratchForward);
106
+ mat4.targetTo(scratchLookMatrix, origin, scratchForward, worldUp);
107
+ return quat.fromMat4(out, scratchLookMatrix);
108
+ }
109
+ var scratchGoal = [
110
+ 0,
111
+ 0,
112
+ 0
113
+ ];
114
+ var scratchReference = [
115
+ 0,
116
+ 0,
117
+ 0,
118
+ 1
119
+ ];
120
+ var scratchWorldOffset = [
121
+ 0,
122
+ 0,
123
+ 0
124
+ ];
125
+ var scratchPreviousOffset = [
126
+ 0,
127
+ 0,
128
+ 0
129
+ ];
130
+ var scratchRotation = [
131
+ 0,
132
+ 0,
133
+ 0,
134
+ 1
135
+ ];
136
+ var scratchDelta = [
137
+ 0,
138
+ 0,
139
+ 0
140
+ ];
141
+ var scratchStep = [
142
+ 0,
143
+ 0,
144
+ 0
145
+ ];
146
+ var scratchFrame = [
147
+ 0,
148
+ 0,
149
+ 0,
150
+ 1
151
+ ];
152
+ var scratchFrameInverse = [
153
+ 0,
154
+ 0,
155
+ 0,
156
+ 1
157
+ ];
158
+ /**
159
+ * Damps the tracked point toward the target position plus `targetOffset`, per axis of the camera `offset`'s frame.
160
+ * When `offset` changes, the tracked point turns with it around the target, so moving the camera is never damped.
161
+ * Writes the tracked point to `out` and the reference orientation to `outOrientation`.
162
+ */
163
+ function trackTarget(out, outOrientation, state, params, target, offset, targetOffset, dt) {
164
+ referenceOrientation(scratchReference, state, params.bindingMode, target);
165
+ if (state.hasPrevious) dampQuaternion(state.rotationDamper, state.orientation, scratchReference, params.rotationDamping, dt);
166
+ else {
167
+ quat.copy(state.orientation, scratchReference);
168
+ start(state.rotationDamper);
169
+ }
170
+ quat.copy(outOrientation, state.orientation);
171
+ vec3.add(scratchGoal, target.position, vec3.transformQuat(scratchGoal, targetOffset, outOrientation));
172
+ vec3.transformQuat(scratchWorldOffset, offset, outOrientation);
173
+ if (state.hasPrevious && !vec3.exactEquals(state.previousOffset, offset)) {
174
+ vec3.transformQuat(scratchPreviousOffset, state.previousOffset, outOrientation);
175
+ safeFromToRotation(scratchRotation, scratchPreviousOffset, scratchWorldOffset, worldUp);
176
+ vec3.subtract(scratchDelta, state.trackedPoint, scratchGoal);
177
+ vec3.add(state.trackedPoint, scratchGoal, vec3.transformQuat(scratchDelta, scratchDelta, scratchRotation));
178
+ }
179
+ vec3.copy(state.previousOffset, offset);
180
+ state.hasPrevious = true;
181
+ vec3.cross(scratchDelta, scratchWorldOffset, worldUp);
182
+ if (vec3.squaredLength(scratchDelta) < 1e-10) quat.copy(scratchFrame, outOrientation);
183
+ else quat.fromMat4(scratchFrame, mat4.targetTo(scratchLookMatrix, origin, scratchWorldOffset, worldUp));
184
+ quat.conjugate(scratchFrameInverse, scratchFrame);
185
+ vec3.subtract(scratchDelta, scratchGoal, state.trackedPoint);
186
+ vec3.transformQuat(scratchDelta, scratchDelta, scratchFrameInverse);
187
+ vec3.zero(scratchStep);
188
+ dampVector3(state.damper, scratchStep, scratchDelta, params.damping, dt, params.maxSpeed);
189
+ vec3.add(state.trackedPoint, state.trackedPoint, vec3.transformQuat(scratchStep, scratchStep, scratchFrame));
190
+ return vec3.copy(out, state.trackedPoint);
191
+ }
192
+ //#endregion
193
+ export { createState, needsTargetRotation, prime, referenceOrientation, reset, trackTarget, tracker_exports };
@@ -0,0 +1,11 @@
1
+ import * as damping from './damping.js';
2
+ import type { DampingConstant } from './damping.js';
3
+ /** Stateful wrapper over `damp`. */
4
+ export declare class Damper {
5
+ readonly state: damping.DamperState;
6
+ get velocity(): number;
7
+ set velocity(value: number);
8
+ update(current: number, target: number, dampingTime: DampingConstant, dt: number, maxSpeed?: number, epsilon?: number): number;
9
+ /** Reset the spring state so the next call snaps to the target again. */
10
+ reset(): void;
11
+ }