tosijs-3d 0.8.4 → 0.8.5
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/CHANGELOG.md +300 -0
- package/dist/b3d-aircraft.d.ts +40 -0
- package/dist/b3d-aircraft.d.ts.map +1 -1
- package/dist/b3d-aircraft.js +138 -1
- package/dist/b3d-aircraft.js.map +1 -1
- package/dist/b3d-ambient.d.ts +5 -0
- package/dist/b3d-ambient.d.ts.map +1 -1
- package/dist/b3d-ambient.js +102 -54
- package/dist/b3d-ambient.js.map +1 -1
- package/dist/b3d-cloud-deck.d.ts +49 -0
- package/dist/b3d-cloud-deck.d.ts.map +1 -1
- package/dist/b3d-cloud-deck.js +375 -63
- package/dist/b3d-cloud-deck.js.map +1 -1
- package/dist/b3d-clouds.js +1 -1
- package/dist/b3d-clouds.js.map +1 -1
- package/dist/b3d-controllable.d.ts +3 -0
- package/dist/b3d-controllable.d.ts.map +1 -1
- package/dist/b3d-controllable.js +16 -0
- package/dist/b3d-controllable.js.map +1 -1
- package/dist/b3d-controller.d.ts.map +1 -1
- package/dist/b3d-controller.js.map +1 -1
- package/dist/b3d-input-focus.d.ts.map +1 -1
- package/dist/b3d-input-focus.js +4 -0
- package/dist/b3d-input-focus.js.map +1 -1
- package/dist/b3d-launcher.d.ts +9 -0
- package/dist/b3d-launcher.d.ts.map +1 -1
- package/dist/b3d-launcher.js +24 -2
- package/dist/b3d-launcher.js.map +1 -1
- package/dist/b3d-light-shafts.d.ts +74 -0
- package/dist/b3d-light-shafts.d.ts.map +1 -0
- package/dist/b3d-light-shafts.js +723 -0
- package/dist/b3d-light-shafts.js.map +1 -0
- package/dist/b3d-lightning.d.ts +82 -0
- package/dist/b3d-lightning.d.ts.map +1 -0
- package/dist/b3d-lightning.js +726 -0
- package/dist/b3d-lightning.js.map +1 -0
- package/dist/b3d-panel.d.ts +3 -0
- package/dist/b3d-panel.d.ts.map +1 -1
- package/dist/b3d-panel.js +5 -0
- package/dist/b3d-panel.js.map +1 -1
- package/dist/b3d-skybox.d.ts.map +1 -1
- package/dist/b3d-skybox.js +16 -2
- package/dist/b3d-skybox.js.map +1 -1
- package/dist/b3d-terrain.d.ts.map +1 -1
- package/dist/b3d-terrain.js +11 -7
- package/dist/b3d-terrain.js.map +1 -1
- package/dist/b3d-trail.d.ts +65 -0
- package/dist/b3d-trail.d.ts.map +1 -0
- package/dist/b3d-trail.js +228 -0
- package/dist/b3d-trail.js.map +1 -0
- package/dist/b3d-warhead.d.ts.map +1 -1
- package/dist/b3d-warhead.js +5 -2
- package/dist/b3d-warhead.js.map +1 -1
- package/dist/b3d-water.d.ts +30 -0
- package/dist/b3d-water.d.ts.map +1 -1
- package/dist/b3d-water.js +338 -2
- package/dist/b3d-water.js.map +1 -1
- package/dist/b3d-weather-cell.d.ts +51 -0
- package/dist/b3d-weather-cell.d.ts.map +1 -0
- package/dist/b3d-weather-cell.js +207 -0
- package/dist/b3d-weather-cell.js.map +1 -0
- package/dist/caustics.d.ts +34 -0
- package/dist/caustics.d.ts.map +1 -0
- package/dist/caustics.js +197 -0
- package/dist/caustics.js.map +1 -0
- package/dist/cloud-field.d.ts +33 -0
- package/dist/cloud-field.d.ts.map +1 -1
- package/dist/cloud-field.js +54 -0
- package/dist/cloud-field.js.map +1 -1
- package/dist/cloud-shadows.d.ts +9 -0
- package/dist/cloud-shadows.d.ts.map +1 -1
- package/dist/cloud-shadows.js +14 -0
- package/dist/cloud-shadows.js.map +1 -1
- package/dist/fly-by-wire.d.ts +24 -0
- package/dist/fly-by-wire.d.ts.map +1 -1
- package/dist/fly-by-wire.js +47 -9
- package/dist/fly-by-wire.js.map +1 -1
- package/dist/frame-panel.d.ts +22 -4
- package/dist/frame-panel.d.ts.map +1 -1
- package/dist/frame-panel.js +94 -2
- package/dist/frame-panel.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/land-and-sky.js +31 -1
- package/dist/land-and-sky.js.map +1 -1
- package/dist/light-rays.d.ts +61 -0
- package/dist/light-rays.d.ts.map +1 -0
- package/dist/light-rays.js +113 -0
- package/dist/light-rays.js.map +1 -0
- package/dist/lightning.d.ts +65 -0
- package/dist/lightning.d.ts.map +1 -0
- package/dist/lightning.js +164 -0
- package/dist/lightning.js.map +1 -0
- package/dist/scene-schemas.d.ts.map +1 -1
- package/dist/scene-schemas.js +13 -0
- package/dist/scene-schemas.js.map +1 -1
- package/dist/sdf-lattice.d.ts +26 -0
- package/dist/sdf-lattice.d.ts.map +1 -1
- package/dist/sdf-lattice.js +17 -0
- package/dist/sdf-lattice.js.map +1 -1
- package/dist/tosi-b3d.d.ts +44 -1
- package/dist/tosi-b3d.d.ts.map +1 -1
- package/dist/tosi-b3d.js +137 -22
- package/dist/tosi-b3d.js.map +1 -1
- package/dist/weather.d.ts +47 -0
- package/dist/weather.d.ts.map +1 -0
- package/dist/weather.js +99 -0
- package/dist/weather.js.map +1 -0
- package/package.json +1 -1
- package/static/attributes.json +386 -10
- package/static/attributes.txt +96 -6
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,306 @@ All notable changes to **tosijs-3d**. This project is pre-1.0 (`0.x`), so minor
|
|
|
6
6
|
versions may carry breaking peer-dependency changes — each is called out in a
|
|
7
7
|
**⚠️ Breaking** block in its version section below, with what a consumer must do.
|
|
8
8
|
|
|
9
|
+
## 0.8.5
|
|
10
|
+
|
|
11
|
+
**Weather you can watch.** Storms that darken the day and strike: lightning
|
|
12
|
+
that lights the cloud from below, inside and above, lights the landscape and
|
|
13
|
+
throws shadows, with thunder at the speed of sound. Shafts of sun through a
|
|
14
|
+
broken sky, and the sky and sun seen through the water from below, with rays
|
|
15
|
+
fanning down from them. Rain and snow from the weather, the wind carrying
|
|
16
|
+
aircraft and buffeting them in a storm. And two long-hidden bugs: the cloud
|
|
17
|
+
deck's local weather was mirrored north-south, and on the doc site no shadow
|
|
18
|
+
map had rendered at all.
|
|
19
|
+
|
|
20
|
+
Size: barrel (min, packages external) 883.2 KB raw / 295.6 KB gz (+5.7% gz),
|
|
21
|
+
for lightning, light shafts, weather cells, trails and caustics.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **Lightning lit the land through cloud-shaped shadows** (Tonio: "the
|
|
26
|
+
directional light seems to be coming from above the cloud layer ... the
|
|
27
|
+
shadows are mostly cloud"). The projected cloud shadow multiplied the
|
|
28
|
+
whole lit colour, flash included; a flash starts BELOW the cloud, so the
|
|
29
|
+
cloud shadow now fades while the deck is flashing (`strengthSource`, read
|
|
30
|
+
at draw time).
|
|
31
|
+
- **Moonlight made shafts as bright as noon.** The shafts' colour was
|
|
32
|
+
normalised and never scaled by the light's intensity; the skybox puts the
|
|
33
|
+
moon in the same light at night. They now scale with it (moon shafts are
|
|
34
|
+
real, and faint).
|
|
35
|
+
- **Shafts are SMALL where they leave the deck or the surface** (Tonio: the
|
|
36
|
+
wider they are, the more obvious any mismatch with the gap): sky `width`
|
|
37
|
+
200 -> 40 m (4 m near closed cover), underwater rays 0.2-0.8 m.
|
|
38
|
+
|
|
39
|
+
- **No shadow map rendered on the doc site, the sun's included.** Babylon's
|
|
40
|
+
shadow generators lazy-load their shaders from code-split chunks, and each
|
|
41
|
+
chunk loaded a second copy of the site bundle (tosijs-ui#191), which threw,
|
|
42
|
+
so the shaders never loaded and every `isReady()` stayed false. The site
|
|
43
|
+
entry now imports the shadow shaders statically and tells the generators
|
|
44
|
+
they are loaded (site-only workaround; the library is unaffected).
|
|
45
|
+
|
|
46
|
+
- **Thunder kept playing after leaving the page** (Tonio). Thunder is
|
|
47
|
+
scheduled ahead on the audio clock (a storm 2 km off rumbles 6 s after its
|
|
48
|
+
flash, for 4 s), and disposing `<tosi-b3d-lightning>` neither stopped it
|
|
49
|
+
nor closed the context. It now closes its AudioContext, silencing
|
|
50
|
+
anything queued at once and no longer leaking a context per visit.
|
|
51
|
+
|
|
52
|
+
- **The cloud deck's local-weather texture was MIRRORED north-south.**
|
|
53
|
+
Babylon's ground rows run from +Z to -Z; the texture's rows the other way.
|
|
54
|
+
Everything reading the texture (local coverage, storm gloom, the cloud
|
|
55
|
+
shadow) put storms and orographic cloud at the mirror image of where they
|
|
56
|
+
were, invisible when a storm sat near the deck's centre. The lightning
|
|
57
|
+
demo's storm, 1.3 km off-centre, was drawn 1.3 km the other way, so every
|
|
58
|
+
strike lit empty sky. Pure `packWeatherTexture` flips the rows, tested.
|
|
59
|
+
- **A storm's sky only closed at its very core**, so from below you looked
|
|
60
|
+
up through gaps at the inside of the tower, which read as the deck's
|
|
61
|
+
BOTTOM bowing upward (Tonio). A storm now counts in full in the coverage
|
|
62
|
+
(its share is taken out of the ramped field and added back whole): a cell
|
|
63
|
+
of 1.8 closes the sky over the inner half of its radius, the base stays
|
|
64
|
+
flat, and only the top skin rises into the tower. From above the ceiling
|
|
65
|
+
bulges up; from below it is a flat, solid underside.
|
|
66
|
+
- **A strike lit the cloud one frame late** (the deck pushed its flash before
|
|
67
|
+
lightning set it); the flash is now written at draw time. It also lights
|
|
68
|
+
the TOP skin, so a tower seen from the side glows, and the ground light
|
|
69
|
+
sits halfway between the cloud base and the terrain under the strike.
|
|
70
|
+
|
|
71
|
+
- **The launcher demo's left stick did nothing** (board #2434). Since the
|
|
72
|
+
GTA-style remap the biped mapping sends A/D and left-stick X to `strafe`
|
|
73
|
+
and only the right stick to `turn`; three doc demos (launcher, warhead,
|
|
74
|
+
the controller's rover) still steered on `turn` alone, so the glass
|
|
75
|
+
pad's stick and A/D were dead. They now steer on either.
|
|
76
|
+
|
|
77
|
+
- **Orographic cloud filled the whole sky over land** (Tonio: "orographic is
|
|
78
|
+
the problem. It fills the transparent areas without changing apparent
|
|
79
|
+
cloud coverage"). The lift was measured from ABSOLUTE height, so with Land
|
|
80
|
+
and Sky's sea at 147 m every bit of land counted as mountain and added
|
|
81
|
+
+0.5 to +0.75 coverage: a 0.3 sky rendered as a solid grey sheet. It is
|
|
82
|
+
now measured from the SEA (the scene's water surface) and weighted to
|
|
83
|
+
RIDGES (ground above its surroundings); a high flat plateau keeps 35% of
|
|
84
|
+
it. Pure: `cloud-field`'s `orographicLift`, tested. `orographicPeak` is now
|
|
85
|
+
the height above the sea.
|
|
86
|
+
|
|
87
|
+
### Added
|
|
88
|
+
|
|
89
|
+
- **Lightning casts shadows** (Tonio: "spin up a shadow map and retain it
|
|
90
|
+
between strokes and just use it for the brightest strike"). ONE shadow map,
|
|
91
|
+
kept; re-rendered once per new brightest ground strike, never per frame.
|
|
92
|
+
The strike's light is a POINT light by default (`flashLight`), from the
|
|
93
|
+
middle of the channel, so shadows radiate from the bolt (a cube map: six
|
|
94
|
+
renders per strike); `'directional'` is the one-render option for low-end
|
|
95
|
+
devices. Casters within `shadowRange` of you (and of the strike, for a
|
|
96
|
+
point light); `shadows`, `shadowSize`. It replaces the old point light, so
|
|
97
|
+
the scene stays within a material's 4-light budget. The lightning demo now
|
|
98
|
+
has hills, trees and a hamlet under the storm.
|
|
99
|
+
- **A storm darkens the day around it** (Tonio: "cut ambient and even sun
|
|
100
|
+
brightness somewhat when lightning is flashing ... by half"): new
|
|
101
|
+
`darken` on `<tosi-b3d-lightning>` (0.5) takes the sun and the ambient
|
|
102
|
+
fill down by half at full storm, easing with distance and strength,
|
|
103
|
+
through the cloud deck's own light handling (`deck.stormDim`) so the two
|
|
104
|
+
cannot compound. The deck's gloom no longer dims lightning's own lights
|
|
105
|
+
(it was cutting the landscape flash by up to 90% under cover).
|
|
106
|
+
- **Land and Sky: a "lightning storm" toggle** beside the volcano: the storm
|
|
107
|
+
gathers in front of you over 20 s, strikes, rains and throws strike
|
|
108
|
+
shadows, then drifts away east.
|
|
109
|
+
- **Lightning is dramatic** (Tonio: "having the lightning be dramatically
|
|
110
|
+
bright"): each strike lights the WHOLE landscape from above (falling off
|
|
111
|
+
with the storm's distance), the tower from inside, harder, and the bolt
|
|
112
|
+
carries an additive halo. New `brightness` (the drama) and `rate` (how
|
|
113
|
+
often, a multiple of the natural rate; pure `strikesBetween` takes it,
|
|
114
|
+
tested) on `<tosi-b3d-lightning>`; `groundLight` default 2.5 -> 6. Storm
|
|
115
|
+
lightning also brightens the WHITEOUT when you are inside the cloud. The
|
|
116
|
+
landscape flash is strong enough for a dark ground to read as lit (peak
|
|
117
|
+
3.5, halving at 6 km; the ground light reaches 6 km). The
|
|
118
|
+
demo has a scene panel: storm size,
|
|
119
|
+
how often, cloud cover, brightness, time of day. A storm is no longer a
|
|
120
|
+
TOWER by default (Tonio: "it basically looks terrible"): the deck's
|
|
121
|
+
`stormRise` defaults to 0 (opt-in, domed when on), so a storm is more
|
|
122
|
+
cover and lightning. From below the flash lights the underside and the
|
|
123
|
+
ground, inside it the whiteout, above it the top.
|
|
124
|
+
- **Weather reaches the airframe** (board #1125). `<tosi-b3d-aircraft>` asks
|
|
125
|
+
the scene for the weather where it is: the WIND carries it (it chases an
|
|
126
|
+
air-relative velocity, so a crosswind crabs it downwind), and a STORM
|
|
127
|
+
buffets it — seeded disturbance on pitch, roll and climb that the attitude
|
|
128
|
+
controller fights back toward the stick. Strong wind alone adds a little.
|
|
129
|
+
New attributes **`turbulence`** (`'on'`/`'off'`, default on) and
|
|
130
|
+
**`turbulenceScale`** (default `1`), and a read-only **`turbulenceLevel`**
|
|
131
|
+
(0–1) for a HUD or a debug readout. The disturbance is the pure, seeded
|
|
132
|
+
**`turbulence(t, seed, level)`** in `fly-by-wire`. Nothing happens on the
|
|
133
|
+
ground or in an owner without the weather service.
|
|
134
|
+
- **Light shafts** (WEATHER-DESIGN stage 4, board #1084), to Tonio's model
|
|
135
|
+
(pure half: **`light-rays`**): **`<tosi-b3d-light-shafts>`** hangs shafts
|
|
136
|
+
from the gaps in the cloud deck, BELOW it, running along the sun and
|
|
137
|
+
widening slightly (`spread`), and as broad as the gaps: `width` at the
|
|
138
|
+
0.5 threshold down to slits as the cover closes toward 1. An additive,
|
|
139
|
+
flat fill of the sun's colour — `strength` 0.35 at the cloud, linear to 0 — most prominent looking toward
|
|
140
|
+
the sun (a forward-scatter phase, per pixel), and only where the local
|
|
141
|
+
cover is broken: 0.5 up to (not including) 1. Placement searches a fine
|
|
142
|
+
grid near you as well as a coarse one far out, keeps one shaft per gap,
|
|
143
|
+
and only refuses a shaft that would pass through you, so a deck just
|
|
144
|
+
above your head (Land and Sky) gets shafts too. The same model runs UNDER
|
|
145
|
+
THE WATER: shafts from the surface, bent by Snell's law, sunlight tinted
|
|
146
|
+
by the water's fog, shimmering as cells come and go (`underwater`,
|
|
147
|
+
`underwaterCount`). SURFACE TURBULENCE drives them (the wind over the
|
|
148
|
+
water, its `waveHeight` and `bumpHeight`): calm water gives a few broad,
|
|
149
|
+
slow rays, choppy water many narrow ones that flicker (`waterRoughness`,
|
|
150
|
+
`waterRayShape`; `waterRoughness` on the element reads it back). The doc
|
|
151
|
+
page has an underwater demo. Shafts are RECTANGULAR (`spread` 0), so
|
|
152
|
+
perspective alone makes them radiate from the sun; sky placement is
|
|
153
|
+
weighted hard toward the sun's position in view, and underwater rays are
|
|
154
|
+
biased toward the viewer so the middle of the view is not empty. Rain adds
|
|
155
|
+
to the strength.
|
|
156
|
+
- **The weather-cell demo has a frame of reference** (Tonio: "it has no
|
|
157
|
+
frame of reference so it just looks like leaves blowing around"): a row of
|
|
158
|
+
flagpoles you fly past, each flag showing the wind WHERE IT STANDS
|
|
159
|
+
(streaming downwind, limp in the lee), and the lee's edge drawn as a ring
|
|
160
|
+
on the water.
|
|
161
|
+
- **The sky through the water, from below** (`b3d-water` `undersideSky`,
|
|
162
|
+
default 1; Tonio: "we want to see the sky and sun through and distorted by
|
|
163
|
+
the water surface"). The window no longer shows a flat colour: a small
|
|
164
|
+
reflection probe photographs the sky with its fog and veil OFF, and the
|
|
165
|
+
underside refracts it through the water's own ripples, so the sky and the
|
|
166
|
+
sun arrive bent and moving. Clearest in the shallows, fading with depth,
|
|
167
|
+
giving way to the dark mirror at grazing angles. The probe is HALF-FLOAT
|
|
168
|
+
and captures the sun as HDR (a new skybox uniform, `b3dSunHdr`, 0 in
|
|
169
|
+
normal rendering), so the sun still punches through the partial
|
|
170
|
+
transmission of the surface (Tonio: "our skybox isn't HDR so its glare
|
|
171
|
+
doesn't punch through"). (It replaces a glare sprite that looked fake.) Underwater rays are fewer (`underwaterCount`
|
|
172
|
+
12, lower presence).
|
|
173
|
+
- **Rain and snow from the weather** (WEATHER-DESIGN stage 5, board #1124).
|
|
174
|
+
`b3d-ambient` gains `weather: 'rain' | 'snow'`: emission follows the
|
|
175
|
+
PRECIPITATION where the viewer is, so a storm brings its own rain and it
|
|
176
|
+
eases in and out as the storm passes; the local temperature splits rain
|
|
177
|
+
from snow (sleet between). Rain now draws as STREAKS stretched along its
|
|
178
|
+
velocity, so the wind visibly slants it. Land and Sky's storm rains.
|
|
179
|
+
- **Lightning and thunder** (WEATHER-DESIGN stage 3, board #1123):
|
|
180
|
+
**`<tosi-b3d-lightning>`** strikes under every weather cell with
|
|
181
|
+
`storminess`, seeded (same seed, same storm; frame rate cannot change it).
|
|
182
|
+
Cloud-to-ground strikes draw a jagged, branching bolt that flickers through
|
|
183
|
+
its re-strokes and light the ground; every strike lights the cloud deck from
|
|
184
|
+
INSIDE around it (`deck.flash()`, a new hook: why storms want coverage past
|
|
185
|
+
1); thunder is procedural and arrives at the speed of sound, so you can
|
|
186
|
+
count the distance; and over strong storms, rarely, **sprites**: brief
|
|
187
|
+
red-pink crowns with purple tendrils high above the tower. Each strike
|
|
188
|
+
dispatches `strike` with `{ kind, x, z, t, distance }`. The pure model is
|
|
189
|
+
`lightning.ts` (`strikesBetween`, `boltPath`, `flashAt`, `thunderDelay`).
|
|
190
|
+
Land and Sky's storm now brings lightning.
|
|
191
|
+
- **Weather, stage 2: a storm you can see** (board #1122). A
|
|
192
|
+
`<tosi-b3d-weather-cell>` with `coverage` joins the cloud deck's local
|
|
193
|
+
weather field: denser cloud over it, a greyer, heavier underside (its own
|
|
194
|
+
"gloom" channel, so orographic cloud still never repaints fair weather as
|
|
195
|
+
foul), the storm's shadow on the ground beneath (the shadow reads the same
|
|
196
|
+
field), and full strength even when the global dial says clear. A drifting
|
|
197
|
+
cell re-bakes about once per 10 m of travel.
|
|
198
|
+
Land and Sky has a **storm** toggle in its Weather group: a storm drifting
|
|
199
|
+
with the wind (the scene's wind now matches the deck's) that passes over
|
|
200
|
+
you and recedes into view.
|
|
201
|
+
Cells gain **`grow`** (seconds to gather from nothing to full), so a storm
|
|
202
|
+
builds rather than appearing; the deck re-bakes in 1% strength steps as it
|
|
203
|
+
does. Across SPACE a cell was already gradual: a smoothstep over its whole
|
|
204
|
+
radius, smoothed again by the deck.
|
|
205
|
+
**Storm towers:** cell coverage now runs to 2, and past 1 is THICKNESS,
|
|
206
|
+
as on the deck's own dial: the deck lifts its top skin there by up to
|
|
207
|
+
`stormRise` (1,500 m), whatever the global dial says, so a storm is a dark
|
|
208
|
+
heavy base from below and a bright tower from above, and the thing
|
|
209
|
+
lightning will light from inside. The cell channels get one smoothing pass,
|
|
210
|
+
not the orographic field's four (which flattened a storm's excess from 0.7
|
|
211
|
+
to 0.18). Land and Sky's storm is coverage 1.7.
|
|
212
|
+
- **Weather, stage 1: the weather where you are** (WEATHER-DESIGN.md, board
|
|
213
|
+
#255). `b3d.weatherAt(x, z)` (and `weatherHere()`) answers what every
|
|
214
|
+
weather consumer asks: the scene's base wind plus every
|
|
215
|
+
**`<tosi-b3d-weather-cell>`** that reaches the point, composed per quantity
|
|
216
|
+
(wind and temperature sum, coverage sums clamped, precipitation and
|
|
217
|
+
storminess take the max). Clouds, water and ambient now read the wind AT
|
|
218
|
+
THE VIEWER rather than one scene-wide value, so a lee is calm and a squall
|
|
219
|
+
is local. A cell with `drift="wind"` travels with the wind (a weather
|
|
220
|
+
system), and `lifetime` grows, holds and ends it. The pure model is
|
|
221
|
+
`weather.ts`. Measured on the new page: leaves' wind 12 → 0.96 m/s crossing
|
|
222
|
+
a lee's centre.
|
|
223
|
+
- **Caustics** (board #198, tosijs-3d#16): light through the moving surface,
|
|
224
|
+
dancing on whatever is beneath a `twoSided` `b3d-water` (`caustics`,
|
|
225
|
+
`'auto'` = on whenever `twoSided`; `causticsStrength`, `causticsScale`).
|
|
226
|
+
Projected by world position through a material plugin (the cloud-shadow
|
|
227
|
+
technique), so terrain, hulls and the player all get it with no per-mesh
|
|
228
|
+
setup; slants with the sun, shimmers (two moving layers, combined with
|
|
229
|
+
`min`), fades with depth and fog, and goes with the sun. The pattern is a
|
|
230
|
+
seeded, tiling cellular web (`causticPattern`), with no file to fetch.
|
|
231
|
+
- **One lattice per world, enforced where code can** (board #257,
|
|
232
|
+
tosijs-3d#75): every `extractChunk` result carries its `lattice` identity
|
|
233
|
+
(`latticeIdentity(cfg)`), and `assertLatticesWeld(chunks)` throws on a
|
|
234
|
+
mismatch instead of leaving a crack. TUNNEL-DESIGN.md records the decision
|
|
235
|
+
that carves are world-level objects provinces declare but don't own, so a
|
|
236
|
+
tunnel between provinces is just a carve in the field.
|
|
237
|
+
- **Snell's window: the water's underside** (board #197, tosijs-3d#15). Looking
|
|
238
|
+
up from under a `twoSided` `b3d-water` used to show flat dark blue. Now
|
|
239
|
+
(`underside`, `'auto'` = on whenever `twoSided`) it is a bright window onto
|
|
240
|
+
the sky overhead, darkening to a mirror of the depths toward grazing angles,
|
|
241
|
+
rippling with the same normal map as the surface, and fading in with the
|
|
242
|
+
underwater fog's own band weight. One plane, one draw call, only while
|
|
243
|
+
submerged. `undersideColor` / `undersideDepthColor` tune the two ends. It
|
|
244
|
+
stays OPAQUE and the sky stays fogged, unlike the prototype, so a level look
|
|
245
|
+
under water still sees murk rather than sky.
|
|
246
|
+
- **`b3d.debugFogColor`** (`'#ff00ff'`) paints the composited fog a colour
|
|
247
|
+
nothing else is, to tell fog from surface from sky; also a toggle on the
|
|
248
|
+
Perf Stats panel's new Fog row (with density, end and veil), for a headset.
|
|
249
|
+
- **`<tosi-b3d-trail>`** — a ribbon behind anything that moves (contrails,
|
|
250
|
+
missile smoke, a fast enemy's wake), lifted from manta-recon's engine
|
|
251
|
+
contrails (tosijs-3d#4, board #186). Nest it in the mover, give it a local
|
|
252
|
+
offset; it measures speed at its own emitter (so it works on anything),
|
|
253
|
+
fades below `minSpeed`, takes `underwaterColor` below a `<tosi-b3d-water>`,
|
|
254
|
+
re-attaches when the host's mesh is replaced (respawn, async load), and
|
|
255
|
+
resets on a floating-origin shift. **`attachTrail(node, scene, options)`**
|
|
256
|
+
is the same for a node you hold, such as a spawned missile.
|
|
257
|
+
Missiles get it for free: `<tosi-b3d-launcher missile-trail="on">`, or
|
|
258
|
+
`trail` on `spawnProjectile`/`spawnMissile` for your own rounds.
|
|
259
|
+
- **Frame panels are usable as menus** (board #768, tosijs-3d#92, from
|
|
260
|
+
manta-recon moving its outer game to viewer-relative panels):
|
|
261
|
+
- **They route pointers.** A `panel3d` on a frame panel now takes presses,
|
|
262
|
+
drags and hover from mouse, touch and XR rays (the same routing
|
|
263
|
+
`b3d-svg-plane` has), and repaints immediately on press and release rather
|
|
264
|
+
than on the texture's 400 ms timer. Before, the buttons drew and ignored
|
|
265
|
+
every click, with no error.
|
|
266
|
+
- `attachFramePanel` returns its **`mesh`**.
|
|
267
|
+
- **`resolution`** on `FramePanelSpec` (and `<tosi-b3d-panel resolution>`):
|
|
268
|
+
384 suits a reticle, not a menu of text.
|
|
269
|
+
- **`flatFrame` applies to any panel**, not only hand panels, so
|
|
270
|
+
`flatFrame: 'face'` measures a flat panel's elevation from the VIEW rather
|
|
271
|
+
than the off-screen horizon of a pitched camera.
|
|
272
|
+
- **Flying under water feels like water** (board #185, manta's #3). A
|
|
273
|
+
`submersible` aircraft now meets a thicker MEDIUM below the surface:
|
|
274
|
+
`waterDrag` (×10 by default, the 2010 Manta's air:water ratio) multiplies
|
|
275
|
+
drag, blended over `waterTransition` metres. The controls are unchanged; full
|
|
276
|
+
throttle settles at ~32% of `maxSpeed`. **`surface-crossed`** fires on each
|
|
277
|
+
crossing with `{ entering, point, speed, aircraft }` for splash, wake and
|
|
278
|
+
audio cues, and **`submerged`** (0–1) is readable. In the pure model:
|
|
279
|
+
`FlyByWireConfig.mediumDrag`, and drag now clamps at rest instead of
|
|
280
|
+
overshooting into reverse on a long frame.
|
|
281
|
+
|
|
282
|
+
### Fixed
|
|
283
|
+
|
|
284
|
+
- **Replacing the player left input focus on the removed one** (board #2421,
|
|
285
|
+
from manta-recon's respawn): the new craft got no input and its crash was
|
|
286
|
+
ignored by `b3d-death`. A controllable now releases focus when it is
|
|
287
|
+
disposed, and `adoptIfVacant` treats a disconnected focused entity as a
|
|
288
|
+
vacant seat. No more `releaseFocus()` before the swap.
|
|
289
|
+
- **Ambient wind accumulated every frame and flung particles away**: the
|
|
290
|
+
preset's direction vectors were assigned by reference, and the per-frame
|
|
291
|
+
`direction.set(preset + wind)` wrote into the preset, so the wind grew frame
|
|
292
|
+
on frame (drops at kilometres a second, never seen). Cloned now, and the
|
|
293
|
+
particles take the INHERITED wind (scene and weather cells), not only the
|
|
294
|
+
element's own `windX`/`windZ`.
|
|
295
|
+
- **Flat eye-anchored panels trailed a moving camera by one frame** (board
|
|
296
|
+
#767, found by manta-recon at 2.15 m per frame behind b3d-aircraft's follow
|
|
297
|
+
camera). The flat frames are now posed on `onBeforeCameraRenderObservable`,
|
|
298
|
+
after anything that moves the camera during the render. Measured: 0.000 m
|
|
299
|
+
gap over 64 frames of a camera moving 2 m per frame.
|
|
300
|
+
- **Every scene with a glass gamepad logged a type warning** (`gamepad is
|
|
301
|
+
declared boolean … but was written string`). `gamepad` is genuinely
|
|
302
|
+
`boolean | string` (`true` = the default layout, a string = a layout), so
|
|
303
|
+
it is now a plain property read once at setup rather than a typed attribute.
|
|
304
|
+
Markup (`gamepad`, `gamepad="…"`) and `b3d({ gamepad })` are unchanged.
|
|
305
|
+
- **`b3d-terrain.recenter()` threw away an authored `worldU`/`worldV`** (board
|
|
306
|
+
#458), resetting them to the defaults. It now clears the travel (the
|
|
307
|
+
floating-origin offset) and leaves the placement alone.
|
|
308
|
+
|
|
9
309
|
## 0.8.4
|
|
10
310
|
|
|
11
311
|
**A sky you can actually see the stars in, and a world with things growing on
|
package/dist/b3d-aircraft.d.ts
CHANGED
|
@@ -78,6 +78,23 @@ export declare class B3dAircraft extends B3dControllable {
|
|
|
78
78
|
* (or `groundY`) beneath it.
|
|
79
79
|
*/
|
|
80
80
|
submersible: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* How much thicker water is than air, as a drag multiplier (submersible
|
|
83
|
+
* only). The 2010 Manta ran identical thrust at drag 0.1 above water and
|
|
84
|
+
* 1.0 below, so ×10: full throttle settles at ~32% of `maxSpeed`
|
|
85
|
+
* underwater and the controls feel the same, just heavier.
|
|
86
|
+
*/
|
|
87
|
+
waterDrag: number;
|
|
88
|
+
/**
|
|
89
|
+
* `'off'` ignores the weather: no wind drift, no buffeting. On by default
|
|
90
|
+
* because a calm scene has no weather to feel, so it changes nothing
|
|
91
|
+
* until a wind or a storm is declared.
|
|
92
|
+
*/
|
|
93
|
+
turbulence: "on" | "off";
|
|
94
|
+
/** Scales the buffeting (1 = as the weather says). */
|
|
95
|
+
turbulenceScale: number;
|
|
96
|
+
/** Metres over which the drag blends from air to water across the surface. */
|
|
97
|
+
waterTransition: number;
|
|
81
98
|
crashSpeed: number;
|
|
82
99
|
weapons: string;
|
|
83
100
|
gunRate: number;
|
|
@@ -116,6 +133,17 @@ export declare class B3dAircraft extends B3dControllable {
|
|
|
116
133
|
};
|
|
117
134
|
airspeed: number;
|
|
118
135
|
altitude: number;
|
|
136
|
+
/** Current turbulence 0–1 from the weather here (a HUD or audio can read it). */
|
|
137
|
+
turbulenceLevel: number;
|
|
138
|
+
private _turbulenceSeed;
|
|
139
|
+
/**
|
|
140
|
+
* How far under the water the airframe is, 0 (air) … 1 (fully submerged),
|
|
141
|
+
* blended over `waterTransition`. 0 whenever the scene has no water or the
|
|
142
|
+
* craft is not `submersible`. Read it for camera, audio or HUD cues.
|
|
143
|
+
*/
|
|
144
|
+
submerged: number;
|
|
145
|
+
private _waterEl;
|
|
146
|
+
private _wasUnder;
|
|
119
147
|
throttleLevel: number;
|
|
120
148
|
vtolActive: boolean;
|
|
121
149
|
stalling: boolean;
|
|
@@ -270,6 +298,18 @@ export declare class B3dAircraft extends B3dControllable {
|
|
|
270
298
|
* Water is ground to something that cannot go under it, and scenery to
|
|
271
299
|
* something that can. That is one rule, so it lives in one place.
|
|
272
300
|
*/
|
|
301
|
+
/**
|
|
302
|
+
* THE MEDIUM, sampled at the airframe: 0 in air, 1 underwater, blended
|
|
303
|
+
* across `waterTransition` so the drag change is felt as a thickening
|
|
304
|
+
* rather than a wall. Also the one place that notices the surface being
|
|
305
|
+
* CROSSED, and says so with a `surface-crossed` event (splash, wake, audio,
|
|
306
|
+
* camera cues are the game's; this only reports the moment).
|
|
307
|
+
*
|
|
308
|
+
* The water level is read from the MESH, like the biped's: water is
|
|
309
|
+
* viewer-centred and not origin-shifted, so the mesh is the honest answer.
|
|
310
|
+
* Looked up once and cached; a scene with no water costs nothing per frame.
|
|
311
|
+
*/
|
|
312
|
+
private _medium;
|
|
273
313
|
private skipForCollision;
|
|
274
314
|
/** World nose direction (unit) and a muzzle point `ahead` metres in front.
|
|
275
315
|
* Computed through the WORLD matrix, never node.position: with a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"b3d-aircraft.d.ts","sourceRoot":"","sources":["../src/b3d-aircraft.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"b3d-aircraft.d.ts","sourceRoot":"","sources":["../src/b3d-aircraft.ts"],"names":[],"mappings":"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"}
|
package/dist/b3d-aircraft.js
CHANGED
|
@@ -196,6 +196,8 @@ turns the pilot's head in the cockpit, springs back on release).
|
|
|
196
196
|
| `afterburnerSpeed` | `75` | Speed ceiling while the throttle is held past `maxSpeed`; releasing bleeds back to `maxSpeed`. ≤ `maxSpeed` disables afterburner. |
|
|
197
197
|
| `acceleration` | `12` | Throttle / lean authority (speed change rate) |
|
|
198
198
|
| `vtolSpeed` | `6` | Forward ground speed splitting hover (below) from plane (above). 0 = pure aeroplane, no hover regime. |
|
|
199
|
+
| `reverseSpeed` | `5` | How fast the craft may back up in a hover (m/s); nose up to reverse |
|
|
200
|
+
| `throttleRate` | `0.8` | How fast the trigger moves the throttle LEVER (full travel per second) |
|
|
199
201
|
| `maxPitch` | `35` | Max nose-UP attitude the stick commands (degrees) |
|
|
200
202
|
| `maxDive` | `0` | Max nose-DOWN attitude (degrees); 0 = symmetric with `maxPitch` |
|
|
201
203
|
| `lookRange` | `120` | How far the right stick can swing the view (degrees each way) |
|
|
@@ -212,6 +214,10 @@ turns the pilot's head in the cockpit, springs back on release).
|
|
|
212
214
|
| `hoverCeiling` | `140` | Height above ground above which the trigger is forward thrust regardless of speed (take off vertically, then fly) and the brake can't stall you below `vtolSpeed`. Below it, slowing to a hover gives the vertical trigger back for a vertical landing. 0 = off. |
|
|
213
215
|
| `groundY` | `0` | Assumed ground-plane height (a floor in addition to any terrain colliders) |
|
|
214
216
|
| `submersible` | `false` | Pass THROUGH a water surface instead of treating it as ground. Off by default — a plane hitting the sea should crash |
|
|
217
|
+
| `waterDrag` | `10` | Submersible only: how much thicker water is than air, as a drag multiplier. At ×10, full throttle settles at ~32% of `maxSpeed` underwater |
|
|
218
|
+
| `waterTransition` | `2` | Metres over which drag blends from air to water across the surface |
|
|
219
|
+
| `turbulence` | `'on'` | The weather reaches the airframe: wind makes it drift and crab, storms (storminess) and strong wind buffet it. Changes nothing in a calm scene; `'off'` ignores the weather |
|
|
220
|
+
| `turbulenceScale` | `1` | Scales the buffeting |
|
|
215
221
|
| `crashSpeed` | `8` | Vertical impact speed (m/s) above which a ground contact is a crash |
|
|
216
222
|
| `hudChaseOff` | `false` | Hide the HUD entirely in chase view. By default chase shows the HUD **without the artificial horizon** (which would contradict the real one behind the aircraft); cockpit shows everything, in-scene |
|
|
217
223
|
| `hudSize` | `0.7` | In-cockpit HUD plane size (metres) |
|
|
@@ -308,6 +314,26 @@ serves both directions — there's no second one to author or keep in sync.
|
|
|
308
314
|
On the ground the wings hold level and the turn stick taxi-steers; pulling back
|
|
309
315
|
rotates for takeoff (or a VTOL lifts straight up on the right trigger). A contact
|
|
310
316
|
faster than `crashSpeed`, or banked/inverted, crashes instead of lands.
|
|
317
|
+
## Under water (`submersible`)
|
|
318
|
+
|
|
319
|
+
A `submersible` craft passes through the water surface instead of crashing on
|
|
320
|
+
it, and flies in a thicker MEDIUM once below: drag is multiplied by
|
|
321
|
+
`waterDrag` (default ×10, the 2010 Manta's ratio), blended across
|
|
322
|
+
`waterTransition` metres of the surface. The controls do not change; the
|
|
323
|
+
craft just gets heavier, and full throttle settles at about 32% of
|
|
324
|
+
`maxSpeed`. `submerged` reads 0 in air and 1 fully under.
|
|
325
|
+
|
|
326
|
+
Crossing the surface dispatches **`surface-crossed`** (bubbling), with
|
|
327
|
+
`detail: { entering, point, speed, aircraft }`: `entering` is true going
|
|
328
|
+
down, and `point` is on the surface. Splash, wake, audio and camera cues are
|
|
329
|
+
yours; the event only reports the moment.
|
|
330
|
+
|
|
331
|
+
```javascript
|
|
332
|
+
craft.addEventListener('surface-crossed', ({ detail }) => {
|
|
333
|
+
if (detail.speed > 8) splashAt(detail.point, detail.entering)
|
|
334
|
+
})
|
|
335
|
+
```
|
|
336
|
+
|
|
311
337
|
## Combat: three things that used to fail by doing nothing
|
|
312
338
|
|
|
313
339
|
Reported together by manta-recon (#23), because they compound — an AI aircraft
|
|
@@ -348,7 +374,7 @@ import * as BABYLON from '@babylonjs/core';
|
|
|
348
374
|
import { canonicalize, applyCenterOfGravity } from './model-transform.js';
|
|
349
375
|
import { B3dControllable } from './b3d-controllable.js';
|
|
350
376
|
import { aircraftMapping } from './virtual-gamepad.js';
|
|
351
|
-
import { equilibriumSpeed, flyByWireStep, targetVelocity, chaseVelocity, } from './fly-by-wire.js';
|
|
377
|
+
import { equilibriumSpeed, flyByWireStep, targetVelocity, turbulence, chaseVelocity, } from './fly-by-wire.js';
|
|
352
378
|
import { placeOnSurface, boundingBottomOffset, hierarchyExtents, isOff, collidable, } from './b3d-utils.js';
|
|
353
379
|
import { spawnProjectile, spawnMissile } from './b3d-launcher.js';
|
|
354
380
|
import { DestroyableBehavior } from './destroyable-behavior.js';
|
|
@@ -388,6 +414,7 @@ const GROUND_FRICTION = 1.2;
|
|
|
388
414
|
// You must climb this far above the pad before a touchdown can register as a crash. Keeps a
|
|
389
415
|
// wobbly VTOL liftoff (rise a little, tip, settle back) from exploding on takeoff.
|
|
390
416
|
const TAKEOFF_MARGIN = 2.5;
|
|
417
|
+
let nextTurbulenceSeed = 1;
|
|
391
418
|
export class B3dAircraft extends B3dControllable {
|
|
392
419
|
static preferredTagName = 'tosi-b3d-aircraft';
|
|
393
420
|
inputMapping = aircraftMapping();
|
|
@@ -486,6 +513,23 @@ export class B3dAircraft extends B3dControllable {
|
|
|
486
513
|
* (or `groundY`) beneath it.
|
|
487
514
|
*/
|
|
488
515
|
submersible: false,
|
|
516
|
+
/**
|
|
517
|
+
* How much thicker water is than air, as a drag multiplier (submersible
|
|
518
|
+
* only). The 2010 Manta ran identical thrust at drag 0.1 above water and
|
|
519
|
+
* 1.0 below, so ×10: full throttle settles at ~32% of `maxSpeed`
|
|
520
|
+
* underwater and the controls feel the same, just heavier.
|
|
521
|
+
*/
|
|
522
|
+
waterDrag: 10,
|
|
523
|
+
/**
|
|
524
|
+
* `'off'` ignores the weather: no wind drift, no buffeting. On by default
|
|
525
|
+
* because a calm scene has no weather to feel, so it changes nothing
|
|
526
|
+
* until a wind or a storm is declared.
|
|
527
|
+
*/
|
|
528
|
+
turbulence: 'on',
|
|
529
|
+
/** Scales the buffeting (1 = as the weather says). */
|
|
530
|
+
turbulenceScale: 1,
|
|
531
|
+
/** Metres over which the drag blends from air to water across the surface. */
|
|
532
|
+
waterTransition: 2,
|
|
489
533
|
// Vertical impact speed (m/s) above which a ground contact is a crash, not
|
|
490
534
|
// a landing.
|
|
491
535
|
crashSpeed: 8,
|
|
@@ -553,6 +597,19 @@ export class B3dAircraft extends B3dControllable {
|
|
|
553
597
|
// Read-only flight state
|
|
554
598
|
airspeed = 0;
|
|
555
599
|
altitude = 0;
|
|
600
|
+
/** Current turbulence 0–1 from the weather here (a HUD or audio can read it). */
|
|
601
|
+
turbulenceLevel = 0;
|
|
602
|
+
// Creation order, not Math.random: the same flight through the same storm
|
|
603
|
+
// must bump the same way.
|
|
604
|
+
_turbulenceSeed = nextTurbulenceSeed++;
|
|
605
|
+
/**
|
|
606
|
+
* How far under the water the airframe is, 0 (air) … 1 (fully submerged),
|
|
607
|
+
* blended over `waterTransition`. 0 whenever the scene has no water or the
|
|
608
|
+
* craft is not `submersible`. Read it for camera, audio or HUD cues.
|
|
609
|
+
*/
|
|
610
|
+
submerged = 0;
|
|
611
|
+
_waterEl = undefined;
|
|
612
|
+
_wasUnder = null;
|
|
556
613
|
throttleLevel = 0;
|
|
557
614
|
vtolActive = false;
|
|
558
615
|
stalling = false;
|
|
@@ -824,6 +881,7 @@ export class B3dAircraft extends B3dControllable {
|
|
|
824
881
|
offLevelSink: attrs.maxSpeed * 0.12,
|
|
825
882
|
diveBoost: attrs.maxSpeed * 0.4,
|
|
826
883
|
velChase: VEL_CHASE,
|
|
884
|
+
mediumDrag: 1 + Math.max(0, attrs.waterDrag - 1) * this._medium(node),
|
|
827
885
|
};
|
|
828
886
|
// Regime is picked by forward GROUND speed OR height above ground: you take
|
|
829
887
|
// off vertically, then the trigger converts to forward thrust once you clear
|
|
@@ -844,6 +902,31 @@ export class B3dAircraft extends B3dControllable {
|
|
|
844
902
|
? Number.POSITIVE_INFINITY
|
|
845
903
|
: this._lastGroundDist - this.groundClearance;
|
|
846
904
|
flyByWireStep(this.fbw, cmd, fwdSpeed, heightAboveGround, cfg, dt, this.grounded);
|
|
905
|
+
/*
|
|
906
|
+
THE WEATHER REACHES THE AIRFRAME (WEATHER-DESIGN, board #1125). Where the
|
|
907
|
+
craft is: the wind makes it DRIFT (it chases an air-relative velocity,
|
|
908
|
+
so a crosswind crabs it), and a storm BUFFETS it: seeded disturbance
|
|
909
|
+
added to the attitude and to the climb, which the attitude controller
|
|
910
|
+
then fights back toward the stick. Not on the ground, and off with
|
|
911
|
+
turbulence="off".
|
|
912
|
+
*/
|
|
913
|
+
const weather = this.grounded || isOff(attrs.turbulence)
|
|
914
|
+
? null
|
|
915
|
+
: this.owner?.weatherAt?.(node.position.x, node.position.z) ?? null;
|
|
916
|
+
if (weather != null) {
|
|
917
|
+
const windSpeed = Math.hypot(weather.wind.x, weather.wind.z);
|
|
918
|
+
const level = Math.min(1, weather.storminess + (windSpeed / 40) * 0.5) *
|
|
919
|
+
Math.max(0, attrs.turbulenceScale ?? 1);
|
|
920
|
+
this.turbulenceLevel = level;
|
|
921
|
+
if (level > 0) {
|
|
922
|
+
const tb = turbulence(this.owner?.frameInfo?.().elapsed ?? 0, this._turbulenceSeed, level);
|
|
923
|
+
this.fbw.pitch += tb.pitchRate * dt;
|
|
924
|
+
this.fbw.bank += tb.rollRate * dt;
|
|
925
|
+
vel.y += tb.heave * dt;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
else
|
|
929
|
+
this.turbulenceLevel = 0;
|
|
847
930
|
// Realise the attitude as a quaternion. Babylon's +pitch(X) drops the nose
|
|
848
931
|
// and +roll(Z) banks left, so negate both (our state: +pitch = nose up,
|
|
849
932
|
// +bank = right). Verified through the rig test.
|
|
@@ -854,6 +937,12 @@ export class B3dAircraft extends B3dControllable {
|
|
|
854
937
|
// Velocity eases toward where the nose points (the "go where you're pointing"
|
|
855
938
|
// chase) — this is what makes it forgiving instead of a skiddy simulation.
|
|
856
939
|
const tv = targetVelocity(this.fbw, cmd, { x: this._fwd.x, y: this._fwd.y, z: this._fwd.z }, fwdSpeed, heightAboveGround, cfg);
|
|
940
|
+
// The air moves: what the craft chases is its air-relative velocity plus
|
|
941
|
+
// the wind, so it drifts downwind and crabs across a crosswind.
|
|
942
|
+
if (weather != null) {
|
|
943
|
+
tv.x += weather.wind.x;
|
|
944
|
+
tv.z += weather.wind.z;
|
|
945
|
+
}
|
|
857
946
|
chaseVelocity(vel, tv, cfg.velChase, dt);
|
|
858
947
|
// Read-only flight state for the HUD / XR rig.
|
|
859
948
|
this.airspeed = this.fbw.speed;
|
|
@@ -1304,6 +1393,50 @@ export class B3dAircraft extends B3dControllable {
|
|
|
1304
1393
|
* Water is ground to something that cannot go under it, and scenery to
|
|
1305
1394
|
* something that can. That is one rule, so it lives in one place.
|
|
1306
1395
|
*/
|
|
1396
|
+
/**
|
|
1397
|
+
* THE MEDIUM, sampled at the airframe: 0 in air, 1 underwater, blended
|
|
1398
|
+
* across `waterTransition` so the drag change is felt as a thickening
|
|
1399
|
+
* rather than a wall. Also the one place that notices the surface being
|
|
1400
|
+
* CROSSED, and says so with a `surface-crossed` event (splash, wake, audio,
|
|
1401
|
+
* camera cues are the game's; this only reports the moment).
|
|
1402
|
+
*
|
|
1403
|
+
* The water level is read from the MESH, like the biped's: water is
|
|
1404
|
+
* viewer-centred and not origin-shifted, so the mesh is the honest answer.
|
|
1405
|
+
* Looked up once and cached; a scene with no water costs nothing per frame.
|
|
1406
|
+
*/
|
|
1407
|
+
_medium(node) {
|
|
1408
|
+
if (this.submersible !== true) {
|
|
1409
|
+
this.submerged = 0;
|
|
1410
|
+
return 0;
|
|
1411
|
+
}
|
|
1412
|
+
if (this._waterEl === undefined) {
|
|
1413
|
+
this._waterEl =
|
|
1414
|
+
this.owner?.querySelector('tosi-b3d-water') ?? null;
|
|
1415
|
+
}
|
|
1416
|
+
const mesh = this._waterEl?.mesh;
|
|
1417
|
+
if (mesh == null) {
|
|
1418
|
+
this.submerged = 0;
|
|
1419
|
+
return 0;
|
|
1420
|
+
}
|
|
1421
|
+
const waterY = mesh.absolutePosition.y;
|
|
1422
|
+
const y = node.position.y;
|
|
1423
|
+
const band = Math.max(1e-3, this.waterTransition ?? 2);
|
|
1424
|
+
this.submerged = Math.min(1, Math.max(0, (waterY - y) / band + 0.5));
|
|
1425
|
+
const under = y < waterY;
|
|
1426
|
+
if (this._wasUnder !== null && under !== this._wasUnder) {
|
|
1427
|
+
this.dispatchEvent(new CustomEvent('surface-crossed', {
|
|
1428
|
+
bubbles: true,
|
|
1429
|
+
detail: {
|
|
1430
|
+
entering: under,
|
|
1431
|
+
point: { x: node.position.x, y: waterY, z: node.position.z },
|
|
1432
|
+
speed: this.velocity.length(),
|
|
1433
|
+
aircraft: this,
|
|
1434
|
+
},
|
|
1435
|
+
}));
|
|
1436
|
+
}
|
|
1437
|
+
this._wasUnder = under;
|
|
1438
|
+
return this.submerged;
|
|
1439
|
+
}
|
|
1307
1440
|
skipForCollision() {
|
|
1308
1441
|
const own = this.ownMeshes();
|
|
1309
1442
|
const submersible = this.submersible === true;
|
|
@@ -2045,6 +2178,10 @@ export class B3dAircraft extends B3dControllable {
|
|
|
2045
2178
|
}
|
|
2046
2179
|
}
|
|
2047
2180
|
sceneDispose() {
|
|
2181
|
+
// The water element belongs to the old scene; the next one may have none.
|
|
2182
|
+
this._waterEl = undefined;
|
|
2183
|
+
this._wasUnder = null;
|
|
2184
|
+
this.submerged = 0;
|
|
2048
2185
|
// Stop waiting for a library that may never come — see `loadFromLibrary`.
|
|
2049
2186
|
this._stopLibraryWait?.();
|
|
2050
2187
|
this._groundDbgOff?.();
|