16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 05:29:18 +02:00
Commit Graph

9 Commits

Author SHA1 Message Date
maj00r
4a9bfdc0aa Section-index visual streaming (no per-cycle twin re-scan)
Replaces the camera-distance ring passes with section-following streaming and a
persistent section index, so a million-node scenery no longer re-scans the whole
twin every time the camera moves into new ground.

- v9 node marker also stores range_max; a model visible from beyond the stream
  radius (or unlimited) is built once up front, the rest stream by section so
  distant landmarks/traction/buildings don't pop out while flora stays local.
- Reader gains node_offset()/seek_node(); cParser exposes the deepest twin's
  file/path/offset/params and seekReplayNode/setReplayParams to rebuild one node.
- First visual pass indexes every deferred node (models via the dispatch fast
  path, origin-placed flora/shapes in deserialize_node) under its region section
  while building the spawn area; later cycles rebuild only the newly-wanted
  sections by seeking straight to their nodes -- O(visible), not O(whole twin).
- Build-all fallback retained for ghostview with no camera centre.

Known: absolute terrain triangles (no origin) still build in the first pass; only
origin-placed content section-streams. Untested in-game (format bump needs a
rebake).
2026-06-24 23:56:53 +02:00
maj00r
06d44b50b0 fixed eventlauncher parsing
ringall mode in ghostmode
2026-06-23 23:00:54 +02:00
maj00r
d7a3e1310a Replace per-node text capture with camera-distance ring multi-pass
The previous nearest-first build captured every deferred visual node as text into a
sorted vector, which does not scale: one tomaszewo flora file alone holds 440k model
nodes (the scenery has 1M+), so the capture ran the process to ~7 GB and its
enumeration never finished.

Stream the visual nodes in camera-distance rings instead, with no per-node capture
(O(1) memory). The visual pass replays the twin once per ring (nearest first); a node
is built only when its squared distance to the camera -- sampled once when the visual
phase starts, so the partition is stable across passes -- falls in the current ring,
otherwise the rest of its body is skipped in O(1) by jumping over the v6 marker span.
Each node is therefore built exactly once, in roughly nearest-first order, through the
normal node path (instancing buckets unchanged). Explicit triangles/lines shapes have
no single position to ring-test by, so they build in the nearest ring pass only.

Reader gains skip_to_node_end() (remembers the served node's end and jumps the cursor
there); cParser::skipReplayNode() delegates it down the active include child.

Verified: td.scn builds 4 rings, no duplicates, no unexpected tokens, complete ~1s
after the infrastructure pass. tomaszewo stays memory-bounded (no OOM, no duplicates)
where the capture approach previously hung.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 17:41:46 +02:00
maj00r
1160bfecac Stream deferred visual nodes in camera-distance order (nearest first)
The progressive load previously streamed the deferred visual nodes (3d model
instances + terrain shapes/lines) in file order, so distant scenery could load
before the player's surroundings. This builds them nearest-camera first instead.

The visual pass now runs in two steps. Enumeration replays the twin and captures
each visual node verbatim (its resolved tokens as text -- numbers round-trip
losslessly through cParser) together with the transform/group context it was read
under and, for models, its transformed world position. Once the replay is
exhausted the records are sorted by squared distance to the camera (terrain shapes
first so the ground appears before the props on it), then built a budgeted slice
per frame through the normal node path with the captured transform and group
restored -- so placement, grouping and the per-cell instance buckets come out
identical to an in-order load.

Two supporting fixes make out-of-order/late insertion correct:
- a cell/section whose geometry was already baked (the renderer finalised it
  before a deferred node arrived) now appends the new shape/lines straight into
  its live geometry bank instead of merging into vertex-freed geometry, which
  would silently drop it; create_geometry() remembers the bank for every cell.
- events that bind to visual model instances (lights/animation/texture/visible)
  are deferred from InitEvents() to a new InitInstanceEvents() run after the
  visual nodes are built, so their target models exist when they initialise.

Verified on td.scn: playable ~2s, 540 deferred nodes enumerated and built
nearest-first ~0.5s later, no duplicate instances.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 17:11:39 +02:00
maj00r
512595234f Stream visual scenery in the driver (play starts after infrastructure pass)
Splits the progressive load across modes: the loader runs only the first
(infrastructure) pass and then hands off to the driver, so play begins as soon
as tracks/traction/events/signals/the player train are ready. The deferred
visual nodes (3d models, terrain shapes/lines) then stream in from the driver,
a small budget per frame, so the world fills in without a long up-front wait.

- state_serializer: the infrastructure pass now returns to the caller (instead of
  chaining the visual pass), restarting the twin for the visual pass; the visual
  pass uses a small ~8 ms/frame budget and marks the load done at the end. A
  text/compile load (no twin) stays single-pass and finishes as before.
- state_manager: retains the load state across the loader->driver hand-off and
  exposes loading_visuals()/continue_loading_visuals().
- driver_mode::update(): advances the deferred visual load each frame.

Verified on td.scn (playable in ~2 s, visuals complete a few seconds later, no
duplicate objects) and on the large tomaszewo scenery (flora/terrain/models
deferred while infrastructure loads). Inserts run on the main thread before the
render step, so progressive loading needs no locking.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:23:36 +02:00
maj00r
fd8bfdbcf3 Add two-pass progressive scenery load (sequential; infra then visuals)
When replaying a binary twin, load in two passes over the same data: the first
pass loads infrastructure (tracks/traction/events/memcells/sounds + directives),
the second pass loads the visual nodes (3d models, terrain shapes/lines) that the
reader skipped via the v6 node-class markers.

- cParser: setReplayPass() selects the served node class (propagated to include
  children); restartReplay() rewinds the twin for the second pass.
- state_serializer: first pass uses the infrastructure pass; on completion it
  restarts the twin for the visual pass. Stateful directives (trainset, event,
  camera, light, sky, time, ...) are skipped on the visual pass so their side
  effects do not duplicate; transform/group directives re-run so deferred visual
  nodes get correct placement. A text/compile load (no twin) stays single-pass.

Verified: td.scn replays through both passes with no duplicate vehicles/events
and reaches the normal load endpoint. This is the sequential foundation; moving
the visual pass into the driver (so play starts after the infrastructure pass) is
the next step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:10:06 +02:00
3419666070 scale/endscale/localscale per node model 2026-05-10 13:12:49 +02:00
copilot-swe-agent[bot]
7e49aa8740 Rewrite #includes to use explicit subdirectory paths
Co-authored-by: Hirek193 <23196899+Hirek193@users.noreply.github.com>
2026-03-14 19:16:48 +00:00
copilot-swe-agent[bot]
0531086bb9 Reorganize source files into logical subdirectories
Co-authored-by: Hirek193 <23196899+Hirek193@users.noreply.github.com>
2026-03-14 19:01:57 +00:00