Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
26 changes: 21 additions & 5 deletions MODS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1753,14 +1753,18 @@ trees: [
],
```

The **`trees` mod** ships the vegetation of Central Europe: twenty-eight species — spruce,
The **`trees` mod** ships the vegetation of Central Europe: forty-six catalogue entries — spruce,
pine, silver fir, larch, Douglas fir, juniper; beech, oak, hornbeam, birch, alder, two
maples, ash, lime, aspen, Lombardy poplar, two willows, elm, horse chestnut, rowan, wild
cherry, black locust; hazel, hawthorn, elder, blackthorn — each in three individually
shaped variants (`_a`, `_b`, `_c`), four levels of detail, and summer, autumn and winter
models. Broadleaf geometry comes from Midge “Mantissa” Sinnaeve's hand-modelled
cherry, black locust; hazel, hawthorn, elder, blackthorn. The shrub layer adds dog rose,
blackberry, raspberry, dogwood, spindle, guelder rose, alder buckthorn, privet, broom,
bilberry, heather, holly, barberry, fly honeysuckle and sea buckthorn; bracken, nettle and
periwinkle cover the understorey. Each has three individually shaped variants (`_a`,
`_b`, `_c`), four levels of detail and seasonal models. Broadleaf geometry comes from Midge “Mantissa” Sinnaeve's hand-modelled
CC0 packs; conifers use Poly Haven's CC0 Fir Tree 01, Pine Tree 01 and Fir Sapling
models with their authored clean LOD meshes and foliage cards. Birch, cherry and
models with their authored clean LOD meshes and foliage cards. Shrubs and understorey use
Poly Haven's CC0 Shrub 01, Searsia Lucida, Wild Rooibos Bush, Fern 02,
Nettle Plant and Periwinkle Plant meshes. Birch, cherry and
fir photographs supply additional PBR textures. `tools/trees/catalogue.json` maps those
forms to the logical species and `tools/trees/import_mantissa.py` creates game LODs without
procedurally growing a trunk or crown. The first two levels retain source branches and
Expand All @@ -1769,6 +1773,18 @@ individual, with matching height, crown extents and centre. Whole-tree renders b
at 400 m or farther and use that individual's exact LOD0 foliage selection. No LOD
enlarges individual leaves. See `tools/trees/README.md` and `mods/trees/LICENSES.md`.

The same mod also ships 15 **repeatable hedge sections**: `feldhecke`,
`weissdornhecke`, `ligusterhecke`, `hainbuchenhecke` and
`immergruene_hecke`, each as `_a`, `_b` and `_c`. Formal sections are 6 m long,
the mixed field hedge 8 m; their stated `footprint` is the exact placement
length and width. Put them in the line's `trees:` list, rotate their long model
axis with `yaw_deg`, and place consecutive centres one section length apart.
They deliberately use the vegetation path rather than `objects:`: that keeps
terrain snapping, instancing, seasons and exactly one of their four LODs active.
Near levels combine reduced CC0 source shrubs with thousands of small cards
mapped to individual leaves in the source atlas, so the body stays closed
without becoming a single blurry billboard.

#### Stands

A wood is rarely one species. Any tree object may carry **`stand-…` tags** saying which
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -513,12 +513,12 @@ big the plant is — a 30 m spruce hands from leaf geometry to its whole-tree im
and is drawn to 2.5 km, while a small blackthorn keeps full detail to at least 45 m and is
gone at 700 m.

`mods/trees` fills them: twenty-eight species of Central Europe, three individually shaped
individuals of each, four levels of detail, and summer, autumn and winter models. They are
`mods/trees` fills them: forty-six trees, shrubs and understorey plants of Central Europe,
three individually shaped individuals of each, four levels of detail, and seasonal models. They are
optimised from Midge “Mantissa” Sinnaeve's hand-modelled
[CC0 tree packs](https://mantissa.xyz/free.html) and Poly Haven's CC0
[fir](https://polyhaven.com/a/fir_tree_01), [pine](https://polyhaven.com/a/pine_tree_01)
and [sapling](https://polyhaven.com/a/fir_sapling) models; `tools/trees/import_mantissa.py`
and [plant](https://polyhaven.com/models/plants) models; `tools/trees/import_mantissa.py`
retains source branches and foliage for the first two levels and bakes multi-view
whole-tree impostors only for distances of at least 400 m —
see `tools/trees/README.md`. The route
Expand Down
34 changes: 30 additions & 4 deletions STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1277,16 +1277,41 @@ As of 2026-08-31 · `cargo test --workspace`: **1136 tests green** · clippy and
because a crossarm changed on one side only puts the conductors beside the
insulator strings instead of on them.

- **Artist trees of Central Europe (2026-09-02, `mods/trees`, `tools/trees/`):** the
- **Artist vegetation of Central Europe (2026-09-02, `mods/trees`, `tools/trees/`):** the
old ez-tree procedural catalogue and its texture/geometry generators were removed.
The 28 logical species and all 84 stable object ids now use modified models from
The original 28 logical tree and large-shrub species and all 84 stable object ids use modified models from
Midge “Mantissa” Sinnaeve’s CC0 broadleaf artist packs and Poly Haven's CC0
Fir Tree 01, Pine Tree 01 and Fir Sapling models; the birch, cherry and fir
packs supply additional optimised bark/foliage photographs. Exact-family forms
are used where available; the remaining catalogue species select one of ten
artist-authored growth forms and apply species height and crown proportions. The
provenance and the deliberate generic mappings are recorded in `mods/trees/LICENSES.md`.

Eighteen further entries fill the shrub and understorey layer: dog rose, blackberry,
raspberry, dogwood, spindle, guelder rose, alder buckthorn, privet, broom, bilberry,
heather, holly, barberry, fly honeysuckle and sea buckthorn, plus bracken, nettle and
periwinkle. They keep complete hand-modelled Poly Haven Shrub 01, Searsia Lucida,
Wild Rooibos Bush, Fern 02, Nettle Plant and Periwinkle Plant meshes and their authored
reduced LOD where supplied. The
public-API downloader verifies Poly Haven's MD5 records; the six source assets and
authors are recorded next to the original sources in `mods/trees/LICENSES.md`.

Fifteen repeatable hedge sections add mixed field, hawthorn, privet, hornbeam and
evergreen formal hedges in three forms each. They introduce no new source material:
`tools/trees/build_hedges.py` composes overlapping reduced instances of the audited CC0
plants under twelve hedge-wide LOD roots and closes their silhouette with small cards,
each mapped to one leaf of the Poly Haven CC0 atlas — never a near whole-hedge
billboard. No hedge-wide or whole-plant impostor is used: the far levels keep thinning
subsets of the reduced 3D source meshes and enlarge only individual leaf cards.
The 6 m formal and 8 m field sections can be placed end to end without gaps
and retain the source plants' summer, autumn and winter forms. Their audited LOD
triangle maxima are 84,351 / 81,151 / 54,303 / 54,103 / 40,579 / 40,379 /
33,517 / 33,317 / 26,455 / 26,255 / 22,624 / 18,993. Eleven handoffs from
60 through 900 m replace the former coarse jumps; the distant levels retain
4,500–5,100 spatially distributed cards. Projected leaf coverage progresses as
100 / 311 / 557 / 972 / 1,696 / 2,866 / 4,763 / 7,656 / 11,150 / 16,017 /
22,104 / 30,250 percent.

`tools/trees/import_mantissa.py` is an import/optimisation tool, not a generator: it
retains source trunks, branches and spatially selected actual source leaves or
foliage cards. Poly Haven conifers start from their artist-authored clean LOD meshes.
Expand All @@ -1299,8 +1324,9 @@ As of 2026-08-31 · `cargo test --workspace`: **1136 tests green** · clippy and
only at 15× tree height (at least 400 m), and the crossed version at 30× height (at least
800 m); the `LOD0` hand-over remains 3.5× height with a 45 m floor.

The checked-in audit covers **84 objects and 237 seasonal models**. Triangle maxima
are 161,169 (`LOD0`), 50,630 (`LOD1`), 8 (`LOD2`) and 4 (`LOD3`). LOD1 retains
The checked-in audit covers **153 objects and 429 seasonal models**: 138 individual
vegetation objects plus 15 hedge sections. Triangle maxima for individual plants
are 175,626 (`LOD0`), 53,424 (`LOD1`), 8 (`LOD2`) and 4 (`LOD3`). LOD1 retains
at least 65% measured leaf surface and targets 80% projected crown coverage, with
source leaves capped at 1.55× size. All materials are dielectric PBR with
explicit roughness, every external buffer/texture reference resolves, and the four
Expand Down
65 changes: 18 additions & 47 deletions THIRD_PARTY_LICENSES.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,53 +273,24 @@ same carriageway. Recompressed from the ambientCG 1K JPEGs (resize, quality

## Trees in `mods/trees/`

The vegetation is generated out of
[EZ-Tree](https://github.com/dgreenheck/ez-tree) by `tools/trees/` (see its
README). EZ-Tree is © 2024 Daniel Greenheck and licensed under the MIT
licence:

> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software […] THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
> OF ANY KIND.

Nothing of its code is included and nothing of it is redistributed: the
pipeline clones the pinned commit into `~/.cache/connected-rails/ez-tree`,
runs it, and keeps only what it grew. The **branch and leaf placement** of the
models therefore comes out of EZ-Tree's generator, and
`tools/trees/lib/mesh.mjs` meshes that skeleton with the same ring-and-quad
construction the library uses — the credit in the `copyright` field of every
generated glTF says so.

The **leaves and needles are photographs**, from two public-domain libraries:

- **[ambientCG](https://ambientcg.com)** — the `LeafSet###` atlases, sheets of
single leaves scanned on black with an opacity map. Twenty-six of the thirty
are used, one or two per species: an oak takes `LeafSet016` in summer and
`LeafSet012` in autumn, a beech `LeafSet024` and `LeafSet015`, an ash the
whole compound sprays of `LeafSet002`.
- **[Poly Haven](https://polyhaven.com)** — the twig atlases of `fir_tree_01`
and `pine_tree_01`, which is what the spruce, the silver fir, the Douglas fir
and the pine carry. Their tree *models* are not used, only those two texture
sets, and only the colour and opacity maps of them.

Both libraries release everything under **CC0 1.0 Universal**
(<https://creativecommons.org/publicdomain/zero/1.0/>) — public domain, no
attribution required. The credit here is given because it is deserved.

Nothing of either is redistributed: `tools/trees/fetch_foliage.mjs` downloads
them into `~/.cache/connected-rails/foliage/`, `lib/leaves.mjs` cuts the single
leaves out of the sheets, and what is checked in is the atlas the build composes
from them — cropped, rotated, tinted and arranged into a foliage card. CC0
allows the derivation without condition.

The **bark is still painted**, from the species entry by
`tools/trees/lib/bark.mjs` — a birch has to be white with black lenticels and a
Scots pine orange-red in plates, and no generic scan gives that. The impostors
are rasterised from the models themselves by `lib/impostor.mjs`. Both are
content of this repository under its own licence.
The shipped vegetation is optimized from hand-modelled and scanned artist
assets by Midge “Mantissa” Sinnaeve and [Poly Haven](https://polyhaven.com).
Every source is released under **CC0 1.0 Universal**
(<https://creativecommons.org/publicdomain/zero/1.0/>), which permits copying,
modification and commercial redistribution. The checked-in glTFs, textures and
impostors are modified derivatives; the multi-gigabyte untouched source files
remain in the local build cache.

The six Mantissa tree archives, nine Poly Haven assets, their authors, direct
source pages, transformations and the deliberate generic botanical mappings
are recorded precisely in [`mods/trees/LICENSES.md`](mods/trees/LICENSES.md).
`tools/trees/fetch_polyhaven.py` obtains Poly Haven's 1K packages through its
public API and verifies the published MD5 sums. `tools/trees/import_mantissa.py`
performs metric scaling, mesh reduction, alpha-atlas packing, PBR conversion,
seasonal grading and the near/far LOD export. It does not procedurally grow a
tree or bush. `tools/trees/build_hedges.py` introduces no further source: it
arranges those audited CC0 plants into repeatable hedge sections while keeping
their materials, seasons and LOD geometry.

## Sounds in `mods/example/assets/sounds/`

Expand Down
5 changes: 5 additions & 0 deletions crates/content/src/demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ fn demo_trees() -> Vec<TreeSource> {
"holunder",
"schlehe",
"weissdorn",
"hundsrose",
"brombeere",
"roter_hartriegel",
"liguster",
"besenginster",
"eberesche",
"sandbirke",
"zitterpappel",
Expand Down
51 changes: 51 additions & 0 deletions mods/_vegetation_showcase/lines/schau.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Three rows beside a short presentation track, all at natural scale.
(
name: "Vegetationsschau",
fictional: true,
geoid_offset: 46.0,
nodes: [Buffer, Buffer],
edges: [
(
from: 0,
to: 1,
start: Geo(point: (lat: 52.0, lon: 10.0, height: 100.0), heading_deg: 90.0),
segments: [(len: 250.0, k0: 0.0, dk: 0.0)],
speed: [(0.0, 40.0)],
),
],
sections: [(edges: [0])],
// Use the streamed vegetation path so exactly one distance LOD is visible.
// The coordinates mirror s=32..57 m and offsets=6/12/18 m on the track.
trees: [
// Back row: tall shrubs.
(object: "trees:stechpalme_b", lat: 51.9999461, lon: 10.0004669, yaw_deg: 95.0, scale: 1.0),
(object: "trees:faulbaum_b", lat: 51.9999461, lon: 10.0005398, yaw_deg: 130.0, scale: 1.0),
(object: "trees:roter_hartriegel_b", lat: 51.9999461, lon: 10.0006128, yaw_deg: 235.0, scale: 1.0),
(object: "trees:sanddorn_b", lat: 51.9999461, lon: 10.0006857, yaw_deg: 350.0, scale: 1.0),
(object: "trees:pfaffenhuetchen_b", lat: 51.9999461, lon: 10.0007587, yaw_deg: 25.0, scale: 1.0),
(object: "trees:schneeball_b", lat: 51.9999461, lon: 10.0008316, yaw_deg: 280.0, scale: 1.0),

// Middle row: hedge and berry shrubs.
(object: "trees:liguster_b", lat: 51.9998922, lon: 10.0004669, yaw_deg: 185.0, scale: 1.0),
(object: "trees:heckenkirsche_b", lat: 51.9998922, lon: 10.0005398, yaw_deg: 70.0, scale: 1.0),
(object: "trees:berberitze_b", lat: 51.9998922, lon: 10.0006128, yaw_deg: 115.0, scale: 1.0),
(object: "trees:hundsrose_b", lat: 51.9998922, lon: 10.0006857, yaw_deg: 20.0, scale: 1.0),
(object: "trees:brombeere_b", lat: 51.9998922, lon: 10.0007587, yaw_deg: 250.0, scale: 1.0),
(object: "trees:himbeere_b", lat: 51.9998922, lon: 10.0008316, yaw_deg: 140.0, scale: 1.0),

// Front row: heath and understorey.
(object: "trees:besenginster_b", lat: 51.9998383, lon: 10.0004669, yaw_deg: 330.0, scale: 1.0),
(object: "trees:besenheide_b", lat: 51.9998383, lon: 10.0005398, yaw_deg: 80.0, scale: 1.0),
(object: "trees:heidelbeere_b", lat: 51.9998383, lon: 10.0006128, yaw_deg: 205.0, scale: 1.0),
(object: "trees:adlerfarn_b", lat: 51.9998383, lon: 10.0006857, yaw_deg: 300.0, scale: 1.0),
(object: "trees:brennnessel_b", lat: 51.9998383, lon: 10.0007587, yaw_deg: 35.0, scale: 1.0),
(object: "trees:immergruen_b", lat: 51.9998383, lon: 10.0008316, yaw_deg: 15.0, scale: 1.0),

// Repeatable hedge sections, aligned along the track.
(object: "trees:feldhecke_b", lat: 51.9998922, lon: 10.0011673, yaw_deg: 0.0, scale: 1.0),
(object: "trees:weissdornhecke_b", lat: 51.9998922, lon: 10.0013424, yaw_deg: 0.0, scale: 1.0),
(object: "trees:ligusterhecke_b", lat: 51.9998922, lon: 10.0015175, yaw_deg: 0.0, scale: 1.0),
(object: "trees:hainbuchenhecke_b", lat: 51.9998922, lon: 10.0016927, yaw_deg: 0.0, scale: 1.0),
(object: "trees:immergruene_hecke_b", lat: 51.9998922, lon: 10.0018678, yaw_deg: 0.0, scale: 1.0),
],
)
10 changes: 10 additions & 0 deletions mods/_vegetation_showcase/mod.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Temporary in-game review scene for the shrub and understorey catalogue.
(
id: "vegetation-showcase",
name: "Vegetationsschau",
version: "1.0.0",
author: "Connected Rails",
description: "Temporäre Ingame-Schaufläche der neuen Vegetation.",
depends: ["trees"],
enabled: true,
)
24 changes: 20 additions & 4 deletions mods/trees/LICENSES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Tree asset licences
# Vegetation asset licences

The broadleaf meshes and some source photographs in this mod are modified
versions of free CG tree packs by **Midge “Mantissa” Sinnaeve** from the
Expand All @@ -20,6 +20,16 @@ official **Poly Haven** assets, also published under CC0 1.0:
- [Pine Tree 01](https://polyhaven.com/a/pine_tree_01) — Rico Cilliers (model), Rob Tuytel (photography)
- [Fir Sapling](https://polyhaven.com/a/fir_sapling)

The shrubs and understorey use modified forms and atlases from these additional
official Poly Haven assets:

- [Shrub 01](https://polyhaven.com/a/shrub_01) — Rico Cilliers
- [Searsia Lucida](https://polyhaven.com/a/searsia_lucida) — James Ray Cock (modeling), Jenelle van Heerden (photography)
- [Wild Rooibos Bush](https://polyhaven.com/a/wild_rooibos_bush) — James Ray Cock (modeling), Jenelle van Heerden (photography)
- [Fern 02](https://polyhaven.com/a/fern_02) — Rob Tuytel (scanning), Rico Cilliers (modeling)
- [Nettle Plant](https://polyhaven.com/a/nettle_plant) — Rob Tuytel (photography), Rico Cilliers (modeling)
- [Periwinkle Plant](https://polyhaven.com/a/periwinkle_plant) — Amal Kumar

Poly Haven's licence terms are recorded on its official
[licence page](https://polyhaven.com/license).

Expand All @@ -29,13 +39,19 @@ attribution. Attribution is nevertheless retained here for provenance.

Connected Rails changes include geometry reduction, removal of underground
roots, metric scaling, PBR material conversion, texture downsampling, seasonal
colour grading and whole-tree LOD impostors. The logical catalogue maps the
artist packs to Central-European species by botanical family and growth form;
generic source forms are used where a species-specific CC0 scan was not
colour grading and whole-plant LOD impostors. Low vegetation keeps the complete
artist mesh because its scanned stem and foliage share one alpha atlas. The
logical catalogue maps the artist packs to Central-European species by growth
form; generic source forms are used where a species-specific CC0 scan was not
available. The catalogue's German/common and botanical names describe game
content; they are not a claim that every generic source form is a botanical
reference specimen.

The hedge objects (`feldhecke_*`, `weissdornhecke_*`, `ligusterhecke_*`,
`hainbuchenhecke_*`, `immergruene_hecke_*`) introduce no additional source
material. They are repeatable compositions of the Mantissa and Poly Haven CC0
models listed above, built by `tools/trees/build_hedges.py`.

These assets are separate mod assets under the additional permission in the
repository’s root `LICENSE`; their CC0 status is compatible with the EUPL-1.2
codebase and with commercial redistribution.
3 changes: 3 additions & 0 deletions mods/trees/assets/adlerfarn_a.bin
Git LFS file not shown
Loading
Loading