@fnndsc/orrery 0.1.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/README.md +12 -0
- package/dist/controls/cameraRig.d.ts +223 -0
- package/dist/controls/cameraRig.js +353 -0
- package/dist/controls/cameraRig.js.map +1 -0
- package/dist/controls/gestures.d.ts +133 -0
- package/dist/controls/gestures.js +282 -0
- package/dist/controls/gestures.js.map +1 -0
- package/dist/controls/index.d.ts +9 -0
- package/dist/controls/index.js +10 -0
- package/dist/controls/index.js.map +1 -0
- package/dist/controls/picker.d.ts +117 -0
- package/dist/controls/picker.js +167 -0
- package/dist/controls/picker.js.map +1 -0
- package/dist/controls/replay.d.ts +94 -0
- package/dist/controls/replay.js +147 -0
- package/dist/controls/replay.js.map +1 -0
- package/dist/draw/censusField.d.ts +113 -0
- package/dist/draw/censusField.js +241 -0
- package/dist/draw/censusField.js.map +1 -0
- package/dist/draw/constants.d.ts +13 -0
- package/dist/draw/constants.js +14 -0
- package/dist/draw/constants.js.map +1 -0
- package/dist/draw/geometry.d.ts +33 -0
- package/dist/draw/geometry.js +55 -0
- package/dist/draw/geometry.js.map +1 -0
- package/dist/draw/handoff.d.ts +11 -0
- package/dist/draw/handoff.js +12 -0
- package/dist/draw/handoff.js.map +1 -0
- package/dist/draw/handoffField.d.ts +74 -0
- package/dist/draw/handoffField.js +151 -0
- package/dist/draw/handoffField.js.map +1 -0
- package/dist/draw/index.d.ts +20 -0
- package/dist/draw/index.js +21 -0
- package/dist/draw/index.js.map +1 -0
- package/dist/draw/labelField.d.ts +63 -0
- package/dist/draw/labelField.js +149 -0
- package/dist/draw/labelField.js.map +1 -0
- package/dist/draw/lamps.d.ts +16 -0
- package/dist/draw/lamps.js +17 -0
- package/dist/draw/lamps.js.map +1 -0
- package/dist/draw/nebula.d.ts +8 -0
- package/dist/draw/nebula.js +28 -0
- package/dist/draw/nebula.js.map +1 -0
- package/dist/draw/palette.d.ts +41 -0
- package/dist/draw/palette.js +32 -0
- package/dist/draw/palette.js.map +1 -0
- package/dist/draw/sphereField.d.ts +98 -0
- package/dist/draw/sphereField.js +168 -0
- package/dist/draw/sphereField.js.map +1 -0
- package/dist/draw/starField.d.ts +127 -0
- package/dist/draw/starField.js +267 -0
- package/dist/draw/starField.js.map +1 -0
- package/dist/draw/stars.d.ts +65 -0
- package/dist/draw/stars.js +132 -0
- package/dist/draw/stars.js.map +1 -0
- package/dist/draw/timing.d.ts +11 -0
- package/dist/draw/timing.js +12 -0
- package/dist/draw/timing.js.map +1 -0
- package/dist/draw/tubeField.d.ts +131 -0
- package/dist/draw/tubeField.js +352 -0
- package/dist/draw/tubeField.js.map +1 -0
- package/dist/draw/tubes.d.ts +41 -0
- package/dist/draw/tubes.js +116 -0
- package/dist/draw/tubes.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/accretion.d.ts +31 -0
- package/dist/layout/accretion.js +384 -0
- package/dist/layout/accretion.js.map +1 -0
- package/dist/layout/constellations.d.ts +25 -0
- package/dist/layout/constellations.js +197 -0
- package/dist/layout/constellations.js.map +1 -0
- package/dist/layout/galaxy.d.ts +12 -0
- package/dist/layout/galaxy.js +99 -0
- package/dist/layout/galaxy.js.map +1 -0
- package/dist/layout/hierarchy.d.ts +45 -0
- package/dist/layout/hierarchy.js +464 -0
- package/dist/layout/hierarchy.js.map +1 -0
- package/dist/layout/index.d.ts +20 -0
- package/dist/layout/index.js +21 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/layout/layoutInput.d.ts +29 -0
- package/dist/layout/layoutInput.js +45 -0
- package/dist/layout/layoutInput.js.map +1 -0
- package/dist/layout/molecule.d.ts +64 -0
- package/dist/layout/molecule.js +155 -0
- package/dist/layout/molecule.js.map +1 -0
- package/dist/layout/pull.d.ts +94 -0
- package/dist/layout/pull.js +137 -0
- package/dist/layout/pull.js.map +1 -0
- package/dist/layout/ranked.d.ts +75 -0
- package/dist/layout/ranked.js +148 -0
- package/dist/layout/ranked.js.map +1 -0
- package/dist/layout/registry.d.ts +23 -0
- package/dist/layout/registry.js +165 -0
- package/dist/layout/registry.js.map +1 -0
- package/dist/layout/seeded.d.ts +32 -0
- package/dist/layout/seeded.js +48 -0
- package/dist/layout/seeded.js.map +1 -0
- package/dist/layout/types.d.ts +81 -0
- package/dist/layout/types.js +14 -0
- package/dist/layout/types.js.map +1 -0
- package/dist/scene/index.d.ts +6 -0
- package/dist/scene/index.js +7 -0
- package/dist/scene/index.js.map +1 -0
- package/dist/scene/orrery.d.ts +592 -0
- package/dist/scene/orrery.js +1555 -0
- package/dist/scene/orrery.js.map +1 -0
- package/dist/types/encoding.d.ts +43 -0
- package/dist/types/encoding.js +7 -0
- package/dist/types/encoding.js.map +1 -0
- package/dist/types/space.d.ts +12 -0
- package/dist/types/space.js +10 -0
- package/dist/types/space.js.map +1 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# @fnndsc/orrery
|
|
2
|
+
|
|
3
|
+
The model of the heavens a surface draws. An orrery is the geared model of the sky on a desk: gearing computes where each body stands, brass spheres show it, a crank sets it turning. This package is that instrument for ARGUS's universe and DAG views, in three layers kept strictly apart, and a scene that composes them:
|
|
4
|
+
|
|
5
|
+
- `layout/` — the gearing. Pure engines (graph in, positions out), no renderer, run in a worker and tested in jest.
|
|
6
|
+
- `draw/` — the spheres. Draws positions with an encoding; knows nothing of layouts or the camera.
|
|
7
|
+
- `controls/` — the crank. Camera rig and flights, pointer gestures, picking.
|
|
8
|
+
- `scene/` — the instrument assembled: `Orrery<N>`, one three.js space a surface mounts, handed nodes with a look (state, a named paint, ember, waved), a palette and optionally a layout worker; every pick hands the surface its own node back.
|
|
9
|
+
|
|
10
|
+
orrery knows nothing of ChRIS: a surface translates its own domain into orrery's encoding (ARGUS does it once, in `apps/argus/src/scene/chrisLook.ts` and `chrisSpace.ts`). The layers' imports are enforced in CI (`npm run lint:orrery`). Design and journal: [docs/orrery.adoc](docs/orrery.adoc).
|
|
11
|
+
|
|
12
|
+
Private to the mise workspace until something besides ARGUS uses it.
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The camera rig: the eye, the world it turns, and the flights
|
|
3
|
+
* between one stance and the next.
|
|
4
|
+
*
|
|
5
|
+
* A scene is looked at by one perspective camera and turned as one world
|
|
6
|
+
* (a group every drawer hangs from). The rig owns both motions and nothing
|
|
7
|
+
* else: which nodes to frame, and why, stays with its caller, which hands
|
|
8
|
+
* in world points and radii. It keeps
|
|
9
|
+
*
|
|
10
|
+
* - the FOCUS, the world point looked at: the pivot of the idle spin and
|
|
11
|
+
* the orbit, the target of the dolly, carried by a pan and moved by a
|
|
12
|
+
* flight that frames something;
|
|
13
|
+
* - the FLIGHT under way, eased in position and aim together;
|
|
14
|
+
* - the HOLD while the camera is parked inside a node, and the stance it
|
|
15
|
+
* flies back to;
|
|
16
|
+
* - whether the operator has TOUCHED the camera since the scene last framed
|
|
17
|
+
* itself, and the pause of the idle spin after every touch.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
import * as THREE from 'three';
|
|
22
|
+
/** Idle rotation speed, radians per frame. */
|
|
23
|
+
export declare const SPIN_INTERACTIVE: number;
|
|
24
|
+
/** The ambient tumble's rotation speed, radians per frame. */
|
|
25
|
+
export declare const SPIN_AMBIENT: number;
|
|
26
|
+
/**
|
|
27
|
+
* How fast the ambient tumble axis wanders, radians of phase per frame.
|
|
28
|
+
* Well below the spin rate, so the motion reads as one continuous freeform
|
|
29
|
+
* tumble rather than a wobble.
|
|
30
|
+
*/
|
|
31
|
+
export declare const TUMBLE_DRIFT: number;
|
|
32
|
+
/** How long after the last touch the idle spin stays paused. */
|
|
33
|
+
export declare const SPIN_RESUME_MS: number;
|
|
34
|
+
/** How long a fly-in and its fly-back take. */
|
|
35
|
+
export declare const FLIGHT_INTO_MS: number;
|
|
36
|
+
/** The world's up: the axis the idle spin and a sideways orbit turn about. */
|
|
37
|
+
export declare const WORLD_UP: THREE.Vector3;
|
|
38
|
+
/**
|
|
39
|
+
* One drawn thing as a framing needs it: where it stands in the world and
|
|
40
|
+
* how far it reaches.
|
|
41
|
+
*/
|
|
42
|
+
export interface WorldReach {
|
|
43
|
+
position: THREE.Vector3;
|
|
44
|
+
radius: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* How a framing parks the camera.
|
|
48
|
+
*
|
|
49
|
+
* @property minDistance - The closest the camera stands, however small the thing.
|
|
50
|
+
* @property margin - Room around the thing, as a factor of the fitting distance.
|
|
51
|
+
* @property stance - `axis` looks down the depth axis; `threeQuarter` opens
|
|
52
|
+
* on an orbit, so a cloud grown from near-planar anchors reads as volume.
|
|
53
|
+
* @property farFloor - The far plane's floor.
|
|
54
|
+
* @property farScale - The far plane as a factor of distance plus radius.
|
|
55
|
+
*/
|
|
56
|
+
export interface FrameOptions {
|
|
57
|
+
minDistance: number;
|
|
58
|
+
margin: number;
|
|
59
|
+
stance: 'axis' | 'threeQuarter';
|
|
60
|
+
farFloor: number;
|
|
61
|
+
farScale: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Smoothstep: gentle leave, gentle arrive.
|
|
65
|
+
*
|
|
66
|
+
* @param t - Progress, 0..1.
|
|
67
|
+
* @returns The eased progress.
|
|
68
|
+
*/
|
|
69
|
+
export declare function ease_smooth(t: number): number;
|
|
70
|
+
/**
|
|
71
|
+
* The camera and the world it turns, steered.
|
|
72
|
+
*/
|
|
73
|
+
export declare class CameraRig {
|
|
74
|
+
private readonly camera;
|
|
75
|
+
private readonly world;
|
|
76
|
+
private readonly clock;
|
|
77
|
+
/** The world point the camera looks at. */
|
|
78
|
+
readonly focus: THREE.Vector3;
|
|
79
|
+
private flight;
|
|
80
|
+
private home;
|
|
81
|
+
private holding;
|
|
82
|
+
private touched;
|
|
83
|
+
private spinIdleUntil;
|
|
84
|
+
private readonly tumbleAxis;
|
|
85
|
+
private tumblePhase;
|
|
86
|
+
/**
|
|
87
|
+
* @param camera - The eye.
|
|
88
|
+
* @param world - The group every drawer hangs from; turns move it.
|
|
89
|
+
* @param clock - Wall-clock milliseconds; `Date.now` unless a test drives time.
|
|
90
|
+
* @param tumblePhase - Where the ambient tumble's wander starts; random so
|
|
91
|
+
* miniatures side by side do not turn in step.
|
|
92
|
+
*/
|
|
93
|
+
constructor(camera: THREE.PerspectiveCamera, world: THREE.Object3D, clock?: () => number, tumblePhase?: number);
|
|
94
|
+
/** @returns Whether a flight is under way. */
|
|
95
|
+
flying(): boolean;
|
|
96
|
+
/** @returns Whether the camera is parked inside a node. */
|
|
97
|
+
holding_get(): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Whether the operator has placed the camera since the scene last framed
|
|
100
|
+
* itself: a repaint of the same space keeps a placed camera.
|
|
101
|
+
*
|
|
102
|
+
* @returns True once touched since the last framing.
|
|
103
|
+
*/
|
|
104
|
+
touched_get(): boolean;
|
|
105
|
+
/** The operator placed the camera: a repaint must not reframe it. */
|
|
106
|
+
touch_note(): void;
|
|
107
|
+
/** The operator is steering: the idle spin waits a while. */
|
|
108
|
+
spin_pause(): void;
|
|
109
|
+
/** @returns The distance from the eye to the focus. */
|
|
110
|
+
eyeDistance(): number;
|
|
111
|
+
/**
|
|
112
|
+
* Turns the world about an axis through the focus.
|
|
113
|
+
*
|
|
114
|
+
* @param axis - A unit axis in world space.
|
|
115
|
+
* @param angle - Radians.
|
|
116
|
+
*/
|
|
117
|
+
turn_about(axis: THREE.Vector3, angle: number): void;
|
|
118
|
+
/**
|
|
119
|
+
* Orbits about the focus by a screen drag: across turns about the world's
|
|
120
|
+
* up, along turns about the camera's right.
|
|
121
|
+
*
|
|
122
|
+
* @param dx - Screen pixels across.
|
|
123
|
+
* @param dy - Screen pixels down.
|
|
124
|
+
*/
|
|
125
|
+
orbit(dx: number, dy: number): void;
|
|
126
|
+
/**
|
|
127
|
+
* Dollies by a wheel's travel. Toward the focus, not the world's origin:
|
|
128
|
+
* after a flight to a feed the camera looks at the feed, and a dolly must
|
|
129
|
+
* close on it. `alongEye` dollies down the eye ray instead, for a camera
|
|
130
|
+
* parked off-axis, where closing on the focus slid the view sideways.
|
|
131
|
+
*
|
|
132
|
+
* @param deltaY - The wheel's travel; positive draws back.
|
|
133
|
+
* @param alongEye - Dolly along the look direction, unclamped.
|
|
134
|
+
*/
|
|
135
|
+
dolly(deltaY: number, alongEye?: boolean): void;
|
|
136
|
+
/**
|
|
137
|
+
* Slides the camera in its own plane by a screen distance; the focus
|
|
138
|
+
* rides along, so the next turn pivots on what is now in the middle.
|
|
139
|
+
*
|
|
140
|
+
* @param dx - Screen pixels across.
|
|
141
|
+
* @param dy - Screen pixels down.
|
|
142
|
+
*/
|
|
143
|
+
pan(dx: number, dy: number): void;
|
|
144
|
+
/**
|
|
145
|
+
* Parks the camera on a thing at once: the world is moved so the thing's
|
|
146
|
+
* centre lies at the origin, the focus goes there, and the camera stands
|
|
147
|
+
* back far enough to hold its radius in both directions of the view.
|
|
148
|
+
*
|
|
149
|
+
* @param center - The thing's centre, in the world group's own space.
|
|
150
|
+
* @param radius - How far it reaches.
|
|
151
|
+
* @param options - How to park; see {@link FrameOptions}.
|
|
152
|
+
*/
|
|
153
|
+
frame(center: THREE.Vector3, radius: number, options?: Partial<FrameOptions>): void;
|
|
154
|
+
/** The scene framed itself: the camera is the scene's again, not the operator's. */
|
|
155
|
+
touch_clear(): void;
|
|
156
|
+
/**
|
|
157
|
+
* Flies to frame a set of things: the framing those things alone would
|
|
158
|
+
* get, reached from where the camera stands, along the line it already
|
|
159
|
+
* looks down, so the flight reads as a dolly and never a swing.
|
|
160
|
+
*
|
|
161
|
+
* @param reaches - The things, in world space.
|
|
162
|
+
* @param durationMs - The flight's length.
|
|
163
|
+
* @param onDone - Called on arrival (at once when there is nothing).
|
|
164
|
+
* @param bulk - The share of the things the frame must hold, 0..1: at 1
|
|
165
|
+
* every outlier is inside; lower lets the farthest few spill, so a
|
|
166
|
+
* settle that throws a few far out does not shrink the bulk to specks.
|
|
167
|
+
* @param margin - Room around, as a factor of the fitting distance.
|
|
168
|
+
*/
|
|
169
|
+
flyToFit(reaches: ReadonlyArray<WorldReach>, durationMs: number, onDone: () => void, bulk?: number, margin?: number): void;
|
|
170
|
+
/**
|
|
171
|
+
* Flies toward one thing, along the line the camera already looks down,
|
|
172
|
+
* to a distance where its neighbourhood fills the view.
|
|
173
|
+
*
|
|
174
|
+
* @param reach - The thing, in world space.
|
|
175
|
+
* @param distance - How far from it to stop; never closer than four radii.
|
|
176
|
+
* @param durationMs - The flight's length.
|
|
177
|
+
* @param onDone - Called on arrival.
|
|
178
|
+
*/
|
|
179
|
+
flyToward(reach: WorldReach, distance: number, durationMs: number, onDone: () => void): void;
|
|
180
|
+
/**
|
|
181
|
+
* Flies into a thing: aims at it from the current stance, then dollies to
|
|
182
|
+
* just shy of its surface, and holds there — no spin, no new flight —
|
|
183
|
+
* until {@link flyBack}. The stance is remembered to fly back to.
|
|
184
|
+
*
|
|
185
|
+
* @param target - The thing's centre, in world space.
|
|
186
|
+
* @param onArrived - Called once inside.
|
|
187
|
+
* @returns False when a flight or a hold already has the camera.
|
|
188
|
+
*/
|
|
189
|
+
flyInto(target: THREE.Vector3, onArrived: () => void): boolean;
|
|
190
|
+
/**
|
|
191
|
+
* Flies back out to the stance before the fly-in and releases the hold.
|
|
192
|
+
*
|
|
193
|
+
* @param onDone - Called once home (at once when there is no stance to return to).
|
|
194
|
+
*/
|
|
195
|
+
flyBack(onDone: () => void): void;
|
|
196
|
+
/**
|
|
197
|
+
* Advances the flight, if any: position and aim eased together. Calls the
|
|
198
|
+
* flight's arrival once it lands.
|
|
199
|
+
*/
|
|
200
|
+
flight_step(): void;
|
|
201
|
+
/**
|
|
202
|
+
* The idle spin, one frame's worth: turns about the world's up unless the
|
|
203
|
+
* operator touched the camera lately, a flight or a hold has it, or the
|
|
204
|
+
* caller says the space must stand still (a pointer over it, a flat view).
|
|
205
|
+
*
|
|
206
|
+
* @param allowed - Whether the caller lets the space turn.
|
|
207
|
+
*/
|
|
208
|
+
spin_step(allowed: boolean): void;
|
|
209
|
+
/**
|
|
210
|
+
* The ambient tumble, one frame's worth: constant angular speed about an
|
|
211
|
+
* axis that itself drifts, so a miniature turns through every orientation
|
|
212
|
+
* rather than orbiting one axis. Incommensurate frequencies keep the
|
|
213
|
+
* wander from settling into a repeating figure.
|
|
214
|
+
*/
|
|
215
|
+
tumble_step(): void;
|
|
216
|
+
/** The distance at which a radius fills the view in both directions. */
|
|
217
|
+
private fitDistance;
|
|
218
|
+
/** The aim a camera at a position would have looking at a target. */
|
|
219
|
+
private aim_from;
|
|
220
|
+
/** Flies to stand a distance from a centre, along the current line of sight. */
|
|
221
|
+
private flyAlongLine;
|
|
222
|
+
private flight_begin;
|
|
223
|
+
}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file The camera rig: the eye, the world it turns, and the flights
|
|
3
|
+
* between one stance and the next.
|
|
4
|
+
*
|
|
5
|
+
* A scene is looked at by one perspective camera and turned as one world
|
|
6
|
+
* (a group every drawer hangs from). The rig owns both motions and nothing
|
|
7
|
+
* else: which nodes to frame, and why, stays with its caller, which hands
|
|
8
|
+
* in world points and radii. It keeps
|
|
9
|
+
*
|
|
10
|
+
* - the FOCUS, the world point looked at: the pivot of the idle spin and
|
|
11
|
+
* the orbit, the target of the dolly, carried by a pan and moved by a
|
|
12
|
+
* flight that frames something;
|
|
13
|
+
* - the FLIGHT under way, eased in position and aim together;
|
|
14
|
+
* - the HOLD while the camera is parked inside a node, and the stance it
|
|
15
|
+
* flies back to;
|
|
16
|
+
* - whether the operator has TOUCHED the camera since the scene last framed
|
|
17
|
+
* itself, and the pause of the idle spin after every touch.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
import * as THREE from 'three';
|
|
22
|
+
/** Idle rotation speed, radians per frame. */
|
|
23
|
+
export const SPIN_INTERACTIVE = 0.0022;
|
|
24
|
+
/** The ambient tumble's rotation speed, radians per frame. */
|
|
25
|
+
export const SPIN_AMBIENT = 0.006;
|
|
26
|
+
/**
|
|
27
|
+
* How fast the ambient tumble axis wanders, radians of phase per frame.
|
|
28
|
+
* Well below the spin rate, so the motion reads as one continuous freeform
|
|
29
|
+
* tumble rather than a wobble.
|
|
30
|
+
*/
|
|
31
|
+
export const TUMBLE_DRIFT = 0.0035;
|
|
32
|
+
/** How long after the last touch the idle spin stays paused. */
|
|
33
|
+
export const SPIN_RESUME_MS = 10_000;
|
|
34
|
+
/** How long a fly-in and its fly-back take. */
|
|
35
|
+
export const FLIGHT_INTO_MS = 700;
|
|
36
|
+
/** The world's up: the axis the idle spin and a sideways orbit turn about. */
|
|
37
|
+
export const WORLD_UP = new THREE.Vector3(0, 1, 0);
|
|
38
|
+
const FRAME_DEFAULTS = { minDistance: 8, margin: 1.15, stance: 'axis', farFloor: 200, farScale: 2 };
|
|
39
|
+
/**
|
|
40
|
+
* Smoothstep: gentle leave, gentle arrive.
|
|
41
|
+
*
|
|
42
|
+
* @param t - Progress, 0..1.
|
|
43
|
+
* @returns The eased progress.
|
|
44
|
+
*/
|
|
45
|
+
export function ease_smooth(t) {
|
|
46
|
+
return t * t * (3 - 2 * t);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The camera and the world it turns, steered.
|
|
50
|
+
*/
|
|
51
|
+
export class CameraRig {
|
|
52
|
+
camera;
|
|
53
|
+
world;
|
|
54
|
+
clock;
|
|
55
|
+
/** The world point the camera looks at. */
|
|
56
|
+
focus = new THREE.Vector3();
|
|
57
|
+
flight = null;
|
|
58
|
+
home = null;
|
|
59
|
+
holding = false;
|
|
60
|
+
touched = false;
|
|
61
|
+
spinIdleUntil = 0;
|
|
62
|
+
tumbleAxis = new THREE.Vector3(0, 1, 0);
|
|
63
|
+
tumblePhase;
|
|
64
|
+
/**
|
|
65
|
+
* @param camera - The eye.
|
|
66
|
+
* @param world - The group every drawer hangs from; turns move it.
|
|
67
|
+
* @param clock - Wall-clock milliseconds; `Date.now` unless a test drives time.
|
|
68
|
+
* @param tumblePhase - Where the ambient tumble's wander starts; random so
|
|
69
|
+
* miniatures side by side do not turn in step.
|
|
70
|
+
*/
|
|
71
|
+
constructor(camera, world, clock = Date.now, tumblePhase = Math.random() * Math.PI * 2) {
|
|
72
|
+
this.camera = camera;
|
|
73
|
+
this.world = world;
|
|
74
|
+
this.clock = clock;
|
|
75
|
+
this.tumblePhase = tumblePhase;
|
|
76
|
+
}
|
|
77
|
+
/** @returns Whether a flight is under way. */
|
|
78
|
+
flying() {
|
|
79
|
+
return this.flight !== null;
|
|
80
|
+
}
|
|
81
|
+
/** @returns Whether the camera is parked inside a node. */
|
|
82
|
+
holding_get() {
|
|
83
|
+
return this.holding;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Whether the operator has placed the camera since the scene last framed
|
|
87
|
+
* itself: a repaint of the same space keeps a placed camera.
|
|
88
|
+
*
|
|
89
|
+
* @returns True once touched since the last framing.
|
|
90
|
+
*/
|
|
91
|
+
touched_get() {
|
|
92
|
+
return this.touched;
|
|
93
|
+
}
|
|
94
|
+
/** The operator placed the camera: a repaint must not reframe it. */
|
|
95
|
+
touch_note() {
|
|
96
|
+
this.touched = true;
|
|
97
|
+
}
|
|
98
|
+
/** The operator is steering: the idle spin waits a while. */
|
|
99
|
+
spin_pause() {
|
|
100
|
+
this.spinIdleUntil = this.clock() + SPIN_RESUME_MS;
|
|
101
|
+
}
|
|
102
|
+
/** @returns The distance from the eye to the focus. */
|
|
103
|
+
eyeDistance() {
|
|
104
|
+
return this.camera.position.distanceTo(this.focus);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Turns the world about an axis through the focus.
|
|
108
|
+
*
|
|
109
|
+
* @param axis - A unit axis in world space.
|
|
110
|
+
* @param angle - Radians.
|
|
111
|
+
*/
|
|
112
|
+
turn_about(axis, angle) {
|
|
113
|
+
const q = new THREE.Quaternion().setFromAxisAngle(axis, angle);
|
|
114
|
+
this.world.position.sub(this.focus).applyQuaternion(q).add(this.focus);
|
|
115
|
+
this.world.quaternion.premultiply(q);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Orbits about the focus by a screen drag: across turns about the world's
|
|
119
|
+
* up, along turns about the camera's right.
|
|
120
|
+
*
|
|
121
|
+
* @param dx - Screen pixels across.
|
|
122
|
+
* @param dy - Screen pixels down.
|
|
123
|
+
*/
|
|
124
|
+
orbit(dx, dy) {
|
|
125
|
+
this.turn_about(WORLD_UP, dx * 0.005);
|
|
126
|
+
this.turn_about(new THREE.Vector3().setFromMatrixColumn(this.camera.matrixWorld, 0).normalize(), dy * 0.005);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Dollies by a wheel's travel. Toward the focus, not the world's origin:
|
|
130
|
+
* after a flight to a feed the camera looks at the feed, and a dolly must
|
|
131
|
+
* close on it. `alongEye` dollies down the eye ray instead, for a camera
|
|
132
|
+
* parked off-axis, where closing on the focus slid the view sideways.
|
|
133
|
+
*
|
|
134
|
+
* @param deltaY - The wheel's travel; positive draws back.
|
|
135
|
+
* @param alongEye - Dolly along the look direction, unclamped.
|
|
136
|
+
*/
|
|
137
|
+
dolly(deltaY, alongEye = false) {
|
|
138
|
+
this.spin_pause();
|
|
139
|
+
this.touched = true;
|
|
140
|
+
if (alongEye) {
|
|
141
|
+
const heading = this.camera.getWorldDirection(new THREE.Vector3());
|
|
142
|
+
const speed = Math.max(4, this.camera.position.length()) * 0.0012;
|
|
143
|
+
this.camera.position.addScaledVector(heading, -deltaY * speed);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const offset = this.camera.position.clone().sub(this.focus);
|
|
147
|
+
const eye = offset.length();
|
|
148
|
+
const next = Math.min(Math.max(eye * Math.exp(deltaY * 0.001), 1.5), Math.max(40, this.camera.far * 0.45));
|
|
149
|
+
this.camera.position.copy(this.focus).addScaledVector(offset, next / Math.max(0.0001, eye));
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Slides the camera in its own plane by a screen distance; the focus
|
|
153
|
+
* rides along, so the next turn pivots on what is now in the middle.
|
|
154
|
+
*
|
|
155
|
+
* @param dx - Screen pixels across.
|
|
156
|
+
* @param dy - Screen pixels down.
|
|
157
|
+
*/
|
|
158
|
+
pan(dx, dy) {
|
|
159
|
+
const factor = this.camera.position.distanceTo(this.focus) * 0.0016;
|
|
160
|
+
const shift = new THREE.Vector3().setFromMatrixColumn(this.camera.matrixWorld, 0).multiplyScalar(-dx * factor)
|
|
161
|
+
.add(new THREE.Vector3().setFromMatrixColumn(this.camera.matrixWorld, 1).multiplyScalar(dy * factor));
|
|
162
|
+
this.camera.position.add(shift);
|
|
163
|
+
this.focus.add(shift);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Parks the camera on a thing at once: the world is moved so the thing's
|
|
167
|
+
* centre lies at the origin, the focus goes there, and the camera stands
|
|
168
|
+
* back far enough to hold its radius in both directions of the view.
|
|
169
|
+
*
|
|
170
|
+
* @param center - The thing's centre, in the world group's own space.
|
|
171
|
+
* @param radius - How far it reaches.
|
|
172
|
+
* @param options - How to park; see {@link FrameOptions}.
|
|
173
|
+
*/
|
|
174
|
+
frame(center, radius, options = {}) {
|
|
175
|
+
const o = { ...FRAME_DEFAULTS, ...options };
|
|
176
|
+
const distance = Math.max(o.minDistance, this.fitDistance(radius) * o.margin);
|
|
177
|
+
this.world.position.copy(center).applyQuaternion(this.world.quaternion).negate();
|
|
178
|
+
this.focus.set(0, 0, 0);
|
|
179
|
+
if (o.stance === 'threeQuarter') {
|
|
180
|
+
this.camera.position.set(distance * 0.5, distance * 0.4, distance * 0.85);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
this.camera.position.set(0, 0, distance);
|
|
184
|
+
}
|
|
185
|
+
this.camera.far = Math.max(o.farFloor, (distance + radius) * o.farScale);
|
|
186
|
+
this.camera.updateProjectionMatrix();
|
|
187
|
+
this.camera.lookAt(0, 0, 0);
|
|
188
|
+
}
|
|
189
|
+
/** The scene framed itself: the camera is the scene's again, not the operator's. */
|
|
190
|
+
touch_clear() {
|
|
191
|
+
this.touched = false;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Flies to frame a set of things: the framing those things alone would
|
|
195
|
+
* get, reached from where the camera stands, along the line it already
|
|
196
|
+
* looks down, so the flight reads as a dolly and never a swing.
|
|
197
|
+
*
|
|
198
|
+
* @param reaches - The things, in world space.
|
|
199
|
+
* @param durationMs - The flight's length.
|
|
200
|
+
* @param onDone - Called on arrival (at once when there is nothing).
|
|
201
|
+
* @param bulk - The share of the things the frame must hold, 0..1: at 1
|
|
202
|
+
* every outlier is inside; lower lets the farthest few spill, so a
|
|
203
|
+
* settle that throws a few far out does not shrink the bulk to specks.
|
|
204
|
+
* @param margin - Room around, as a factor of the fitting distance.
|
|
205
|
+
*/
|
|
206
|
+
flyToFit(reaches, durationMs, onDone, bulk = 1, margin = 1.15) {
|
|
207
|
+
if (reaches.length === 0) {
|
|
208
|
+
onDone();
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
let radiusMax = 0;
|
|
212
|
+
const center = new THREE.Vector3();
|
|
213
|
+
for (const reach of reaches) {
|
|
214
|
+
center.add(reach.position);
|
|
215
|
+
radiusMax = Math.max(radiusMax, reach.radius);
|
|
216
|
+
}
|
|
217
|
+
center.divideScalar(reaches.length);
|
|
218
|
+
const distances = reaches.map((reach) => center.distanceTo(reach.position)).sort((a, b) => a - b);
|
|
219
|
+
const kept = Math.max(1, Math.min(distances.length, Math.ceil(distances.length * Math.min(1, Math.max(0.1, bulk)))));
|
|
220
|
+
const radius = Math.max(1, (distances[kept - 1] ?? 1) + radiusMax);
|
|
221
|
+
const distance = Math.max(3, this.fitDistance(radius) * margin);
|
|
222
|
+
this.camera.far = Math.max(this.camera.far, (distance + radius) * 2);
|
|
223
|
+
this.camera.updateProjectionMatrix();
|
|
224
|
+
this.flyAlongLine(center, distance, durationMs, onDone);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Flies toward one thing, along the line the camera already looks down,
|
|
228
|
+
* to a distance where its neighbourhood fills the view.
|
|
229
|
+
*
|
|
230
|
+
* @param reach - The thing, in world space.
|
|
231
|
+
* @param distance - How far from it to stop; never closer than four radii.
|
|
232
|
+
* @param durationMs - The flight's length.
|
|
233
|
+
* @param onDone - Called on arrival.
|
|
234
|
+
*/
|
|
235
|
+
flyToward(reach, distance, durationMs, onDone) {
|
|
236
|
+
this.flyAlongLine(reach.position, Math.max(distance, reach.radius * 4), durationMs, onDone);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Flies into a thing: aims at it from the current stance, then dollies to
|
|
240
|
+
* just shy of its surface, and holds there — no spin, no new flight —
|
|
241
|
+
* until {@link flyBack}. The stance is remembered to fly back to.
|
|
242
|
+
*
|
|
243
|
+
* @param target - The thing's centre, in world space.
|
|
244
|
+
* @param onArrived - Called once inside.
|
|
245
|
+
* @returns False when a flight or a hold already has the camera.
|
|
246
|
+
*/
|
|
247
|
+
flyInto(target, onArrived) {
|
|
248
|
+
if (this.flight !== null || this.holding)
|
|
249
|
+
return false;
|
|
250
|
+
this.holding = true;
|
|
251
|
+
this.home = { position: this.camera.position.clone(), quaternion: this.camera.quaternion.clone() };
|
|
252
|
+
const toPos = target.clone().add(this.camera.position.clone().sub(target).normalize().multiplyScalar(0.4));
|
|
253
|
+
this.flight_begin(toPos, this.aim_from(this.camera.position, target), FLIGHT_INTO_MS, onArrived);
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Flies back out to the stance before the fly-in and releases the hold.
|
|
258
|
+
*
|
|
259
|
+
* @param onDone - Called once home (at once when there is no stance to return to).
|
|
260
|
+
*/
|
|
261
|
+
flyBack(onDone) {
|
|
262
|
+
const home = this.home;
|
|
263
|
+
if (home === null) {
|
|
264
|
+
this.holding = false;
|
|
265
|
+
onDone();
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
this.flight_begin(home.position.clone(), home.quaternion.clone(), FLIGHT_INTO_MS, () => {
|
|
269
|
+
this.home = null;
|
|
270
|
+
this.holding = false;
|
|
271
|
+
this.spin_pause();
|
|
272
|
+
onDone();
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Advances the flight, if any: position and aim eased together. Calls the
|
|
277
|
+
* flight's arrival once it lands.
|
|
278
|
+
*/
|
|
279
|
+
flight_step() {
|
|
280
|
+
const flight = this.flight;
|
|
281
|
+
if (flight === null)
|
|
282
|
+
return;
|
|
283
|
+
const t = Math.min(1, (this.clock() - flight.startedAt) / flight.durationMs);
|
|
284
|
+
const eased = ease_smooth(t);
|
|
285
|
+
this.camera.position.lerpVectors(flight.fromPos, flight.toPos, eased);
|
|
286
|
+
this.camera.quaternion.slerpQuaternions(flight.fromQuat, flight.toQuat, eased);
|
|
287
|
+
if (t >= 1) {
|
|
288
|
+
this.flight = null;
|
|
289
|
+
flight.onDone();
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* The idle spin, one frame's worth: turns about the world's up unless the
|
|
294
|
+
* operator touched the camera lately, a flight or a hold has it, or the
|
|
295
|
+
* caller says the space must stand still (a pointer over it, a flat view).
|
|
296
|
+
*
|
|
297
|
+
* @param allowed - Whether the caller lets the space turn.
|
|
298
|
+
*/
|
|
299
|
+
spin_step(allowed) {
|
|
300
|
+
if (!allowed || this.holding || this.flight !== null || this.clock() < this.spinIdleUntil)
|
|
301
|
+
return;
|
|
302
|
+
this.turn_about(WORLD_UP, SPIN_INTERACTIVE);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* The ambient tumble, one frame's worth: constant angular speed about an
|
|
306
|
+
* axis that itself drifts, so a miniature turns through every orientation
|
|
307
|
+
* rather than orbiting one axis. Incommensurate frequencies keep the
|
|
308
|
+
* wander from settling into a repeating figure.
|
|
309
|
+
*/
|
|
310
|
+
tumble_step() {
|
|
311
|
+
this.tumblePhase += TUMBLE_DRIFT;
|
|
312
|
+
this.tumbleAxis
|
|
313
|
+
.set(Math.sin(this.tumblePhase * 0.7), Math.cos(this.tumblePhase * 0.4) + 0.6, Math.sin(this.tumblePhase * 0.3) * 0.8)
|
|
314
|
+
.normalize();
|
|
315
|
+
this.world.rotateOnWorldAxis(this.tumbleAxis, SPIN_AMBIENT);
|
|
316
|
+
}
|
|
317
|
+
/** The distance at which a radius fills the view in both directions. */
|
|
318
|
+
fitDistance(radius) {
|
|
319
|
+
const fov = (this.camera.fov * Math.PI) / 180;
|
|
320
|
+
const fitH = radius / Math.tan(fov / 2);
|
|
321
|
+
const fitW = radius / (Math.tan(fov / 2) * Math.max(0.1, this.camera.aspect));
|
|
322
|
+
return Math.max(fitH, fitW);
|
|
323
|
+
}
|
|
324
|
+
/** The aim a camera at a position would have looking at a target. */
|
|
325
|
+
aim_from(position, target) {
|
|
326
|
+
const aim = this.camera.clone();
|
|
327
|
+
aim.position.copy(position);
|
|
328
|
+
aim.lookAt(target);
|
|
329
|
+
return aim.quaternion.clone();
|
|
330
|
+
}
|
|
331
|
+
/** Flies to stand a distance from a centre, along the current line of sight. */
|
|
332
|
+
flyAlongLine(center, distance, durationMs, onDone) {
|
|
333
|
+
const heading = this.camera.position.clone().sub(center);
|
|
334
|
+
if (heading.lengthSq() < 0.0001)
|
|
335
|
+
heading.set(0, 0, 1);
|
|
336
|
+
heading.normalize();
|
|
337
|
+
const toPos = center.clone().add(heading.multiplyScalar(distance));
|
|
338
|
+
this.focus.copy(center);
|
|
339
|
+
this.flight_begin(toPos, this.aim_from(toPos, center), durationMs, onDone);
|
|
340
|
+
}
|
|
341
|
+
flight_begin(toPos, toQuat, durationMs, onDone) {
|
|
342
|
+
this.flight = {
|
|
343
|
+
fromPos: this.camera.position.clone(),
|
|
344
|
+
toPos,
|
|
345
|
+
fromQuat: this.camera.quaternion.clone(),
|
|
346
|
+
toQuat,
|
|
347
|
+
startedAt: this.clock(),
|
|
348
|
+
durationMs,
|
|
349
|
+
onDone,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=cameraRig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cameraRig.js","sourceRoot":"","sources":["../../src/controls/cameraRig.ts"],"names":[],"mappings":"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"}
|