@rr0/ufoathome 0.56.0 → 0.57.1

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 CHANGED
@@ -461,7 +461,6 @@ interface SightingRecordingJson {
461
461
  haloScale: number // 0 = no glow
462
462
  selected: boolean
463
463
  title?: string // shown as an on-canvas tooltip when hovered
464
- behindCloud?: boolean // the witness reported it behind cloud at this instant — stated, never deduced (see below)
465
464
  angular?: { widthDeg: number, heightDeg: number } // how big it LOOKED — the only size a testimony holds, see Apparent size
466
465
  points?: { x: number, y: number }[] // "polygon" shapes only
467
466
  }
@@ -512,8 +511,8 @@ The same rule governs the whole scene, not just the object's own sound: **paused
512
511
  precipitation and its splashes, twinkling stars, lightning flashes, the sun's lens flare and the weather's own
513
512
  ambient beds all stop with the player and resume with it, leaving the frozen frame on screen. A paused replay is
514
513
  one instant of a sighting — weather still going on over it would be the reader's own room, not the witness's
515
- evening. (The cloud deck is not in that list because it does not move at all: its noise field is fixed, with no
516
- time of its own. Real drifting cloud is part of the volumetric-cloud work still to come.)
514
+ evening. Clouds likewise use the recording's timeline: wind advection stops on pause and is
515
+ recomputed deterministically when seeking.
517
516
 
518
517
  ### Naming a place
519
518
 
@@ -599,11 +598,10 @@ values, **read-only**, above a line naming the dataset and the exact UTC instant
599
598
  wrong `utcOffsetHours` shows up there before it shows up in the rendered sky). The request that
600
599
  produced them is kept in `weatherSource.url`, so the claim stays checkable years later.
601
600
 
602
- Two of the fields have no direct counterpart in the record and are *derived* — `cloudDarkness`,
603
- which is a look rather than a measurement (weighted by which layers hold the cloud, plus rain and
604
- thunderstorm), and `cloudBaseM`, placed at the lowest deck holding a real share of the sky, from
605
- Espy's temperature/dew-point spread for a low deck. Both are documented in
606
- `src/engine/weather/providers/OpenMeteoWeatherProvider.ts`.
601
+ Two inputs have no direct counterpart in the record. Layer `darkness` starts from a derived visual
602
+ estimate weighted by cloud level, rain and thunderstorm. A low `baseM` starts from Espy's
603
+ temperature/dew-point spread. Both derivations are documented in
604
+ `src/engine/weather/providers/OpenMeteoWeatherProvider.ts`; crystal alignment is never inferred.
607
605
 
608
606
  Unchecking **From weather records** hands the fields back to the witness: the looked-up values stay
609
607
  as a starting point, `weatherSource` is dropped, and no later lookup may overwrite them — the same
@@ -641,23 +639,6 @@ npx tsx scripts/infer-case-weather.ts --dry-run path/to/sighting.json
641
639
  It rewrites only `weatherTrack` and `weatherSource`, splicing them into the file's own text so the
642
640
  diff shows the weather and nothing else.
643
641
 
644
- ### Behind a cloud
645
-
646
- `behindCloud` is how a recording says "it disappeared into a cloud" — keyframed like any other
647
- appearance field, and held rather than blended. It is *stated*, for the same reason
648
- `DecorObject.occludesSourceIds` is: this format describes an appearance on the witness's own field
649
- of view, not where an object was in space, so nothing in it can deduce whether cloud came between
650
- them. A recording holds no distance at all (see *Apparent size* below) — the distance a shape is
651
- *drawn* at is a parameter of the picture, not a fact (see *Where the shape is drawn*) — and the
652
- sky's own gaps are procedural noise: leaving the question to geometry means tuning the weather
653
- until the reported disappearance happens to occur. So the witness's account is the whole answer: no
654
- `behindCloud`, no cloud, and a shape declared behind cloud is not drawn while the deck is up.
655
-
656
- There used to be a geometric fallback here, for a recording that stated a real distance and made no
657
- claim about cloud. It went when stated distances did, and it had earned it: the one case it fired on
658
- was Chiles-Whitted, where "it disappeared into the cloud deck" turned out to be an interrogator's
659
- reconstruction that Whitted himself denied to McDonald in 1968.
660
-
661
642
  ### Apparent size — and why there is no real one
662
643
 
663
644
  A witness never perceives meters. They perceive an angle: the thing covered a thumbnail at arm's length, or a fifth
@@ -980,3 +961,85 @@ engines.
980
961
  ## License
981
962
 
982
963
  MIT
964
+
965
+ ### Cloud layers
966
+
967
+ `weatherTrack.keyframes[].weather.cloudLayers` overrides the historical cloud fields. An absent
968
+ array adapts the old lower/cirrus values; an empty array means clear sky. Layers are matched by
969
+ stable `id`, not array position. Added and removed layers fade their coverage; altitude, thickness,
970
+ size, density and wind interpolate. Type and seed change at the destination keyframe.
971
+
972
+ ```json
973
+ {
974
+ "id": "low",
975
+ "type": "cumulus",
976
+ "baseM": 1500,
977
+ "thicknessM": 800,
978
+ "coverage": 0.55,
979
+ "sizeM": 1400,
980
+ "density": 1,
981
+ "darkness": 0.2,
982
+ "seed": 17,
983
+ "windDirectionDeg": 90,
984
+ "windSpeed": 5
985
+ }
986
+ ```
987
+
988
+ Base altitude is relative to the recording's reference ground; it must not follow the observer.
989
+ Wind overrides are optional and otherwise use the general weather wind. Advection integrates the
990
+ weather timeline from zero; seeking and pausing reproduce the same field. Coverage controls the
991
+ fraction of the generated horizontal field occupied by cloud, independently of characteristic
992
+ cloud size and optical density.
993
+
994
+ `SceneElement.setCloudRendering("volume")` selects volumetric rendering. `"surface"` remains the default
995
+ and is available for comparison on the existing development page, under the cloud test controls.
996
+ The thick layers use a 64³ byte noise texture, shared within a renderer, 48 view samples and up to
997
+ three light samples per occupied view sample. Continuous weather changes update uniforms without
998
+ recreating meshes or textures. Cirrus still use the lightweight surface renderer.
999
+
1000
+ The volume intersects concentric spherical layers around Earth and shades density along the ray,
1001
+ including from inside or above a layer. Distant detail converges toward average coverage and its
1002
+ colour toward atmospheric haze. Phenomenon textures sample the same density, stopping at each
1003
+ fragment's distance, and celestial attenuation uses a CPU twin of the field.
1004
+
1005
+ Current limits: full-resolution rendering (no temporal reconstruction or adaptive quality yet),
1006
+ back-to-front composition of separate layers (overlapping volumes need joint integration), and
1007
+ terrain occlusion still uses the proxy shell's depth rather than a metre-based depth pre-pass.
1008
+ Thin cirrus use the lighter surface field and share that exact veil with the halo renderer. Crystal
1009
+ alignment belongs to the cirrus layer that carries it, rather than to the whole sky.
1010
+
1011
+ Layers can also contain optional `instances`: individual clouds with stable IDs, east/north
1012
+ positions, base altitude, thickness, width, depth, rotation, density and an optional darkness
1013
+ override. An individual cloud is a piece of its layer's own field — the same noise at the same
1014
+ scale, seed and offset, under the same coverage threshold, lifted to a full cloud inside its
1015
+ ellipsoid and carved out of the layer's deck there — so it is one of its neighbours, told apart by
1016
+ nothing but where it stands and how big it is. It drifts with its layer's wind, attenuates
1017
+ phenomena and celestial bodies, and remains present at zero layer coverage. A layer that holds
1018
+ any is drawn as a volume in both rendering modes: a volume set among a surface's flat texture is
1019
+ a thing of another kind. Instance properties interpolate on the weather timeline.
1020
+
1021
+ The volume's coverage threshold is a quantile like the surface deck's, but fitted to what a ray
1022
+ finds rather than to the field's values at a point (see `coverageThreshold` in
1023
+ `VolumetricClouds.ts`), so a layer's coverage is about the fraction of sky it covers.
1024
+ The weather panel in the recording editor lets you add and remove layers, and add, select, edit
1025
+ and delete their individual clouds using numeric controls. Its optional
1026
+ canvas manipulation mode selects individual clouds by density and drags them in a plane parallel
1027
+ to the image, updating horizontal position and altitude. Drag increments preserve position
1028
+ differences between keyframes and use the same projection as the rendered scene. Valid edits
1029
+ save immediately and pause playback; the default scope is the current weather time. The whole-observation scope explicitly applies the
1030
+ edited property across all weather keyframes, preserving other properties and winds. Layer wind
1031
+ overrides may be left empty to inherit the general wind. Cloud edits take ownership from inferred
1032
+ weather, preventing a pending lookup from replacing the edits. The normal recording export and
1033
+ import retain the layers and instances. The development page only supplies the synthetic scenario
1034
+ and surface/volume comparison; all cloud authoring uses the recording editor.
1035
+
1036
+ `darkness` is stored per layer. An individual cloud may override it or omit it to inherit its
1037
+ parent. `iceCrystalAlignment` is offered only on cirrus and remains author-editable when ERA5 owns
1038
+ the measured fields, because no reanalysis records crystal orientation.
1039
+
1040
+ For inferred Open-Meteo weather, the low, middle and high cloud fractions remain three separate
1041
+ layers with stable identities. They inherit the reported wind and evolve on the weather timeline.
1042
+ The existing total-cover value remains the dataset's total rather than a sum of the bands. Low
1043
+ base altitude is estimated from the temperature/dew-point spread; other dimensions and morphology
1044
+ are rendering assumptions, not observations of individual clouds. Editing clouds manually keeps
1045
+ the established weather-ownership behavior; selecting weather records again restores inference.