@rr0/ufoathome 0.1.0 → 0.2.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 +192 -2
- package/dist-embed/UfoMessages_fr-DKnWFOyl.js +10 -0
- package/dist-embed/rr0-ufo-recorder.mjs +298 -102
- package/dist-embed-scene/UfoMessages_fr-DKnWFOyl.js +10 -0
- package/dist-embed-scene/rr0-scene.mjs +21178 -0
- package/dist-embed-ufo/UfoMessages_fr-DKnWFOyl.js +10 -0
- package/dist-embed-ufo/rr0-ufo.mjs +471 -0
- package/package.json +13 -8
- package/dist-embed-player/rr0-ufo-player.mjs +0 -275
package/README.md
CHANGED
|
@@ -1,5 +1,195 @@
|
|
|
1
1
|
<img src="doc/web/ufoathome/UFOAtHome.png" align=right alt="UFO@home logo">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# UFO@home
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**UFO@home** lets a UFO witness record the shape, appearance and movement of what they saw — and replay it like a VCR —
|
|
6
|
+
instead of relying only on a written or spoken account. The approach follows [Roger Shepard's
|
|
7
|
+
recommendation](https://rr0.org/time/1/9/6/8/07/29/Symposium/Shepard/index_fr.html) that a visual reconstruction of a
|
|
8
|
+
testimony is more faithful than an oral or written one.
|
|
9
|
+
|
|
10
|
+
Originally a Java applet (2003), the project has been rewritten from scratch in TypeScript: a small,
|
|
11
|
+
dependency-light engine (keyframe timeline, recording, playback, Canvas2D rendering) wrapped in three vanilla
|
|
12
|
+
[Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) — no UI framework, no build step
|
|
13
|
+
required by the consuming page. One of the three (`<rr0-scene>`) does pull in [Three.js](https://threejs.org/)
|
|
14
|
+
for an optional 3D backdrop — see [`<rr0-scene>`](#rr0-scene--3d-decor) below for why that's an isolated,
|
|
15
|
+
opt-in bundle rather than a project-wide dependency.
|
|
16
|
+
|
|
17
|
+
### Naming
|
|
18
|
+
|
|
19
|
+
`<rr0-ufo>` is the UFO's own 2D shape/appearance/movement layer — no "player" suffix, since read-only playback is
|
|
20
|
+
its default behavior and `<rr0-ufo-recorder>` is the one that needs a qualifier (it *adds* recording on top).
|
|
21
|
+
`<rr0-scene>` is named without "ufo" on purpose: it only renders a generic 3D decor (sky/horizon/stars) from a
|
|
22
|
+
real-world time and place, with no UFO-specific logic of its own — today it composes a nested `<rr0-ufo>` for the
|
|
23
|
+
common case (see its section below), but the decor itself could back other kinds of reconstructions later. A fully
|
|
24
|
+
generic version (accepting arbitrary overlay content instead of always creating its own `<rr0-ufo>`) is a natural
|
|
25
|
+
follow-up, not implemented yet.
|
|
26
|
+
|
|
27
|
+
See the [Wiki](https://github.com/RR0/UfoAtHome/wiki) for the project's history, and a live example embedded in
|
|
28
|
+
[rr0.org's UFO@home page](https://rr0.org/science/crypto/ufo/enquete/projet/UfoAtHome.html) and in its
|
|
29
|
+
[Chiles-Whitted case reconstruction](https://rr0.org/science/crypto/ufo/enquete/dossier/ChilesWhitted/index.html).
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install @rr0/ufoathome
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Three self-contained, pre-built ES modules are published — each self-registers its custom element as soon as it's
|
|
38
|
+
imported, no explicit setup call needed:
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<script type="module" src="/node_modules/@rr0/ufoathome/dist-embed-ufo/rr0-ufo.mjs"></script>
|
|
42
|
+
<script type="module" src="/node_modules/@rr0/ufoathome/dist-embed/rr0-ufo-recorder.mjs"></script>
|
|
43
|
+
<script type="module" src="/node_modules/@rr0/ufoathome/dist-embed-scene/rr0-scene.mjs"></script>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
or, from a bundler:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import "@rr0/ufoathome/ufo" // registers <rr0-ufo>
|
|
50
|
+
import "@rr0/ufoathome/recorder" // registers <rr0-ufo-recorder> (and <rr0-ufo>, which it composes)
|
|
51
|
+
import "@rr0/ufoathome/scene" // registers <rr0-scene> (and <rr0-ufo>, which it composes)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Only load the one(s) a given page actually needs — `rr0-scene.mjs` in particular pulls in Three.js and is far
|
|
55
|
+
heavier than the other two (see its section below), so pages that just need playback should stick to
|
|
56
|
+
`rr0-ufo.mjs`.
|
|
57
|
+
|
|
58
|
+
## `<rr0-ufo>` — read-only playback
|
|
59
|
+
|
|
60
|
+
The lightweight component (~9KB): a canvas plus Play/Pause/Loop/seek controls. Use it wherever a page only needs to
|
|
61
|
+
*replay* an already-recorded sighting — this is the one to embed in content pages.
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<rr0-ufo src="sighting.json"></rr0-ufo>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
| Member | Kind | Description |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| `src` | attribute | URL of a [`SightingRecordingJson`](#data-format) file, fetched automatically on connect and whenever the attribute changes |
|
|
70
|
+
| `sightingData` | property (get/set) | The current recording as a plain [`SightingRecordingJson`](#data-format) object |
|
|
71
|
+
| `sighting` | property (readonly) | The live `Sighting` model (real-world time/place + the recording's `Timeline`) |
|
|
72
|
+
| `canvasElement` | property (readonly) | The underlying `<canvas>` element |
|
|
73
|
+
| `renderer` | property (readonly) | The `CanvasRenderer` instance painting onto that canvas |
|
|
74
|
+
| `refresh()` | method | Re-reads the timeline's duration into the seek slider and repaints the current frame — call after externally mutating `sighting.timeline` |
|
|
75
|
+
| `loadFromSrc(url)` | method (async) | What the `src` attribute triggers internally; can be called directly too |
|
|
76
|
+
|
|
77
|
+
Playback matches the observation's *real reported duration* when it's known: set `time`/`endTime`, or `time`/
|
|
78
|
+
`durationSeconds`, in the [data format](#data-format) (`durationSeconds` takes precedence over `endTime` if both are
|
|
79
|
+
given). Watching a 5-minute sighting then takes 5 real minutes, not however long the recording itself took to
|
|
80
|
+
author (e.g. a quick mouse drag) — drag the seek bar directly to skip ahead. The start/end labels around the seek
|
|
81
|
+
bar show real clock times when `time` has an hour (e.g. `02:45` → `02:50`); otherwise they show `0:00` → the
|
|
82
|
+
duration actually available (the declared one if known, else the recording's own length). Playback loops by
|
|
83
|
+
default — click the loop button (pressed = looping) to play once and stop instead.
|
|
84
|
+
|
|
85
|
+
## `<rr0-ufo-recorder>` — full editor
|
|
86
|
+
|
|
87
|
+
The authoring component (~17KB): everything `<rr0-ufo>` has, plus a shape/appearance toolbar (oval/saucer/
|
|
88
|
+
triangle presets, color, transparency, halo) and drag-to-record. It composes a `<rr0-ufo>` internally rather
|
|
89
|
+
than duplicating the canvas/playback code — see [Architecture](#architecture).
|
|
90
|
+
|
|
91
|
+
```html
|
|
92
|
+
<rr0-ufo-recorder></rr0-ufo-recorder>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Usage: click **Record**, move the pointer over the canvas to draw the UFO's path, click **Stop**, then **Play** to
|
|
96
|
+
replay it.
|
|
97
|
+
|
|
98
|
+
| Member | Kind | Description |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| `sightingData` | property (get/set) | Delegates to the nested `<rr0-ufo>`'s `sightingData` |
|
|
101
|
+
| `appearance` | property (get/set, accepts a partial object on set) | `{ presetId: "oval" \| "saucer" \| "triangle", color: string, transparency: number, haloScale: number }` — the UFO's appearance used for the next recording |
|
|
102
|
+
|
|
103
|
+
## `<rr0-scene>` — 3D decor
|
|
104
|
+
|
|
105
|
+
The environmental variant (~180KB gzip, dominated by [Three.js](https://threejs.org/) — this is by far the heaviest
|
|
106
|
+
of the three bundles, load it only on pages that want it): everything `<rr0-ufo>` has, composited over a 3D
|
|
107
|
+
sky/horizon/starfield backdrop instead of a plain background. Same markup and members as `<rr0-ufo>` (`src`,
|
|
108
|
+
`sightingData`, `loadFromSrc`) — it's a drop-in upgrade.
|
|
109
|
+
|
|
110
|
+
```html
|
|
111
|
+
<rr0-scene src="sighting.json"></rr0-scene>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Lighting (sky darkness/color, star visibility) is computed from the sighting's own recorded `time`/`place` via
|
|
115
|
+
`src/engine/astronomy/SunPosition.ts` — a vanilla (no dependency) implementation of the standard NOAA/Spencer
|
|
116
|
+
low-precision solar position approximation. Deliberately scoped down for this first pass: only the sun's *altitude*
|
|
117
|
+
drives the sky, not azimuth — positioning a sun/moon disc (or anything else) at a specific compass direction needs
|
|
118
|
+
the witness's viewing heading, which isn't part of the data model yet. Precipitation and optical effects (lens
|
|
119
|
+
flare, halos, mirage) are future work; see `src/render3d/SceneRenderer.ts`.
|
|
120
|
+
|
|
121
|
+
The UFO shape itself deliberately stays a 2D overlay on top of the 3D decor, never "upgraded" to a 3D object: it's
|
|
122
|
+
what the witness reported — possibly a misidentification or optical effect — not something to interpret as a real
|
|
123
|
+
3D shape. Only the surrounding environment, independently computable from real astronomy, is rendered in 3D.
|
|
124
|
+
|
|
125
|
+
## Data format
|
|
126
|
+
|
|
127
|
+
Both components read/write a plain, JSON-serializable `SightingRecordingJson`:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
interface SightingRecordingJson {
|
|
131
|
+
version: 1
|
|
132
|
+
time?: { year?: number, month?: number, day?: number, hour?: number, minute?: number, second?: number }
|
|
133
|
+
endTime?: { year?: number, month?: number, day?: number, hour?: number, minute?: number, second?: number } // alternative to durationSeconds
|
|
134
|
+
durationSeconds?: number // alternative to endTime; takes precedence if both are set
|
|
135
|
+
place?: { lat: number, lng: number }[]
|
|
136
|
+
witnessId?: string
|
|
137
|
+
timeline: {
|
|
138
|
+
keyframes: Array<{
|
|
139
|
+
t: number // milliseconds since recording start
|
|
140
|
+
shapes: Array<{
|
|
141
|
+
sourceId: string // e.g. "ufo-1" — lets several shapes (a UFO, a landmark, a trailing flame...) share one timeline
|
|
142
|
+
shape: {
|
|
143
|
+
kind: "oval" | "polygon"
|
|
144
|
+
bounds: { x: number, y: number, width: number, height: number }
|
|
145
|
+
color: string // CSS color
|
|
146
|
+
angle: number // radians
|
|
147
|
+
transparency: number // 0 = opaque, 1 = fully transparent
|
|
148
|
+
haloScale: number // 0 = no glow
|
|
149
|
+
selected: boolean
|
|
150
|
+
points?: { x: number, y: number }[] // "polygon" shapes only
|
|
151
|
+
}
|
|
152
|
+
}>
|
|
153
|
+
}>
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
This format is deliberately independent of [`@rr0/data`](https://github.com/RR0/data)'s `RR0Event`/`@rr0/time`'s
|
|
159
|
+
`Level2Date`/`@rr0/place`'s `Place` classes, even though its `time`/`place` fields are structurally aligned with
|
|
160
|
+
them — importing those classes into browser-bundled code pulls in Node-only file-scanning dependencies that break a
|
|
161
|
+
`vite build`. `src/engine/interop/rr0Data.ts` converts between the two for Node-side tooling (e.g. generating a
|
|
162
|
+
case's `sighting.json` from its `RR0Event`).
|
|
163
|
+
|
|
164
|
+
## Architecture
|
|
165
|
+
|
|
166
|
+
- `src/engine/` — framework-agnostic core: `model/` (`Shape`, `Timeline`, `Sighting`), `record/` (`Recorder`,
|
|
167
|
+
`SamplingClock`), `playback/` (`Player`), `persistence/` (JSON (de)serialization), `astronomy/` (vanilla solar
|
|
168
|
+
position), `interop/` (real `@rr0/data` conversion, Node-only).
|
|
169
|
+
- `src/render/CanvasRenderer.ts` — paints shapes onto a `<canvas>` 2D context.
|
|
170
|
+
- `src/render3d/` — the Three.js decor renderer (`SceneRenderer`) and its pure, dependency-free color logic
|
|
171
|
+
(`skyColors.ts`), kept separate so the latter is unit-testable without a WebGL context.
|
|
172
|
+
- `src/component/` — the three Web Components. `UfoElement` (`<rr0-ufo>`) owns the canvas/playback; `UfoRecorderElement`
|
|
173
|
+
and `SceneElement` (`<rr0-scene>`) both compose it (via `document.createElement`, not an inline template tag — see
|
|
174
|
+
the comment at that call site) rather than duplicating it, adding recording/appearance-editing or the 3D decor on
|
|
175
|
+
top, respectively.
|
|
176
|
+
- Playback is deliberately discrete (hold-last-keyframe, no interpolation), matching the original applet's behavior.
|
|
177
|
+
- Recording samples the pointer position at a configurable rate via `requestAnimationFrame`, not on every
|
|
178
|
+
`pointermove` event.
|
|
179
|
+
|
|
180
|
+
## Development
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
npm install
|
|
184
|
+
npm run dev # local demo (record + play), Vite dev server
|
|
185
|
+
npm test # vitest
|
|
186
|
+
npm run build # type-check + build the demo
|
|
187
|
+
npm run build:embed # build dist-embed/rr0-ufo-recorder.mjs
|
|
188
|
+
npm run build:embed-ufo # build dist-embed-ufo/rr0-ufo.mjs
|
|
189
|
+
npm run build:embed-scene # build dist-embed-scene/rr0-scene.mjs
|
|
190
|
+
npm run build:all # all four
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
MIT
|