You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(vegetation): TerrainField was stripping anchor kind/biome, so VegetationPlacement saw kind-0 everywhere
Root cause of "trees look like clones / no species variety": createTerrainField re-maps input anchors
to carry a per-anchor height sampler but dropped kind and biome fields. VegetationPlacement reads
anchors[i].kind from field.anchors — got undefined at every cell — fell back to BIOME_KIND[undefined]
?? 0. Every biome in the world was treated as rolling_hills regardless of layout. Willow/fir/palm never
spawned even when standing on a swamp/alpine/beach anchor.
After fix: survivor world 441-chunk probe shows 5/5 tree species (33% oak / 28% pine / 18% willow /
18% fir / 3% palm) vs. previously oak+pine only.
Also in this commit:
- scale/tilt variation: wider scale range 0.75-1.45 (trees), up to ~4.6deg tilt; rand01 upgraded to
proper avalanche mixer because the raw 24-bit extraction correlated narrowly for certain XOR keys.
- SPECIES_WEIGHTS boosted for non-oak trees so IDW-diluted biome weights still cross the spawn gate.
- Three new regressions in test.js covering each of these.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: AGENTS.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,6 +28,8 @@ This file collects facts that are **not derivable by reading the code** and woul
28
28
29
29
-**ez-tree cannot run in Node.** The library's ESM bundle references `document` at import time (used for its texture-loading path). Any Node-side probe of vegetation must either use jsdom or run only the placement sampler (pure math, no ez-tree dep). test.js exercises `VegetationPlacement.js` + `VegetationPhysics.js` only for this reason — `VegetationSystem.js` is browser-only.
30
30
31
+
-**`TerrainField` must preserve anchor `kind` and `biome` when re-mapping.**`createTerrainField` in `src/terrain/TerrainField.js` re-maps input anchors into an internal shape carrying a per-anchor `sampler` for height blending. The mapping MUST carry `kind` and `biome` forward — `VegetationPlacement.speciesFromAnchors` reads `anchors[i].kind` from `field.anchors` (not from the original `generateContinent` output) and silently falls back to `BIOME_KIND[undefined] ?? 0` if the field is missing. Symptom: every biome in the world produces only rolling_hills-weighted species (oak/bush/grass), and mountains/swamp/beach/alpine areas never get pine/fir/willow/palm. test.js has a regression for this; don't skimp on it when refactoring the field.
32
+
31
33
-**Client and server vegetation must use identical placement inputs.** Both sides run `createVegetationPlacement` with the same `seed + terrain config`. If the server has collision capsules but the client's trees are elsewhere, the first thing to check is whether the world's `vegetation.seed` and the `terrain` block are getting through to both `AppRuntime.setVegetationConfig` AND `createVegetationSystem(scene, { ...wd.terrain, ...wd.vegetation })`. Mismatch = invisible trees with capsules in empty ground, or visible trees with no collision.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,8 @@
1
1
## Unreleased
2
2
3
+
- fix(vegetation): `TerrainField` was stripping `kind`/`biome` fields when re-mapping anchors for per-anchor samplers, so `VegetationPlacement` read `anchor.kind === undefined` at every cell and fell back to `BIOME_KIND[undefined] ?? 0` — every cell saw only kind-0 (rolling_hills) weights, so willow/fir/palm never spawned regardless of biome layout. Preserved `kind`/`biome` in `createTerrainField`. After fix: survivor world 441-chunk probe yields 5/5 tree species (33% oak / 28% pine / 18% willow / 18% fir / 3% palm), vs. previously oak/pine only.
4
+
- feat(vegetation): per-tree scale + per-tree tilt variation. Per-species scale jitter widened to 0.75–1.45 (was 0.85–1.25) with tilt up to ~4.6° around Y-axis for organic look. `rand01` upgraded to a proper avalanche mixer because the raw 24-bit extraction correlated narrowly for small XOR keys — previously produced scale min=0.925 max=1.098 despite nominal 0.85–1.25 range. New scale buckets uniform across 0.75–1.45.
5
+
- feat(vegetation): SPECIES_WEIGHTS boosted for non-oak trees — at IDW blend boundaries with dilute biome weights, willow/fir/palm weight × densityScale was falling below the per-cell spawn gate even at the biome's own anchor. Weights in kinds 2/3/4/5/6/7 now produce fir/willow/palm at their respective biome anchors.
3
6
- fix(vegetation): ez-tree API fix — trees now actually render. Previously tree.options.type = TreeType.Oak was producing undefined (TreeType has only Deciduous/Evergreen; species flavor is bark.type + leaves.type). The cascading undefined caused a 'Cannot set properties of undefined (setting length)' in bakeTree that silently failed init. Validated live in browser: 29 chunks, 7/7 species baked.
4
7
- feat(vegetation): ground cover billboard cards (bush/grass) + `setConfig` hot-reload + `WORLD=survivor` env var for multiplayer server. Fixes "no plants visible" — server was loading default world without terrain/vegetation; set `WORLD=survivor` to enable. Client-side `continent: 'default'` string is now expanded to anchors in `VegetationSystem.buildHeightSampler` for placement parity with server. Bushes render as crossed double-plane billboards; grass as single planes with procedural canvas-painted alpha-streak textures.
5
8
- feat(vegetation): procedural vegetation system. `src/terrain/VegetationPlacement.js` = deterministic jittered-grid placement with IDW-blended biome weighting for species picks (oak/pine/fir/willow/palm/bush/grass). `src/physics/VegetationPhysics.js` = chunked Jolt capsule streaming (trees only; bushes/grass are visual only). `client/VegetationSystem.js` = client rendering via ez-tree bake at startup + per-chunk `THREE.InstancedMesh` per species part (trunk/foliage separately). Wired into AppRuntime (`setVegetationConfig`), ServerAPI, WorkerEntry singleplayer, and survivor world. Adds `@dgreenheck/ez-tree` dependency + importmap entry.
0 commit comments