Skip to content

feat(three/tree-layer): crop/fruit visualisation, organic canopy & per-tree variety#533

Merged
charlieforward9 merged 2 commits intomasterfrom
feat/tree-layer-oak-canopy
Feb 28, 2026
Merged

feat(three/tree-layer): crop/fruit visualisation, organic canopy & per-tree variety#533
charlieforward9 merged 2 commits intomasterfrom
feat/tree-layer-oak-canopy

Conversation

@charlieforward9
Copy link
Collaborator

@charlieforward9 charlieforward9 commented Feb 26, 2026

image

Summary

  • getCrop / CropConfig API — new accessor renders live fruit/flower spheres nestled into the outer canopy shell and semi-transparent dropped fruit on the ground; positions are deterministically seeded from each tree's lng/lat so they are stable across re-renders
  • Organic canopy geometry — smooth sinusoidal vertex jitter (jitterSmooth) baked into each species mesh at init time; species-tuned magnitudes (oak ±18 %, cherry ±20 %, birch ±14 %, palm ±10 %); no mesh gaps, zero runtime cost
  • Per-tree silhouette variety — position-derived yaw (correct vertical-axis bearing) + ±15 % asymmetric XY canopy scale give every instance a unique shape with zero extra draw calls
  • Pine tier improvements — per-tier radius/height jitter, drift scaled 0→max from bottom to top so the lowest tier always joins the trunk cleanly
  • Bug fixes — pine level→mesh assignment (separate sub-layer per branch-level count), CANOPY_TRUNK_OVERLAP raised to 0.22, updateTriggers for sizeScale on trunk + canopy sub-layers, crop phi clamped to equatorial band (no crops on canopy crown)
  • Wild-forest example — 9 zones (pines, oaks, palms, birches, cherry blossom, citrus orchard, almond grove); crop toggle checkbox; vite.config.ts for source-aliased HMR without dist rebuild
  • README — full CropConfig type reference, crop placement mechanics, updated feature list, example run instructions

Test plan

  • Run yarn start from examples/three/wild-forest/ and verify all 9 zones render
  • Toggle "Show crops" checkbox — citrus (orange), cherry blossom (pink), almond (tan) spheres appear/disappear
  • Verify live crops sit inside the canopy with tips barely visible, not floating above the crown
  • Verify dropped crops appear on the ground under orchard trees at reduced opacity
  • Drag sizeScale slider — both trunk and canopy scale correctly at all values
  • Hover any tree — tooltip shows species, height, canopy diameter
  • Orbit to confirm each tree has a unique canopy orientation and shape (no two identical)
  • Confirm pine tiers connect to the trunk at the base and drift outward toward the top

🤖 Generated with Claude Code

@charlieforward9 charlieforward9 changed the title feat(tree-layer): smooth oak canopy sphere, matte material feat(three/tree-layer): crop/fruit visualisation, organic canopy & per-tree variety Feb 28, 2026
@charlieforward9 charlieforward9 force-pushed the feat/tree-layer-oak-canopy branch from cae6f89 to b074a48 Compare February 28, 2026 03:19
charlieforward9 and others added 2 commits February 28, 2026 13:41
…-tree variety

## TreeLayer additions

### Crop / fruit / flower (getCrop)
- New `CropConfig` type exported from index: `{ color, count, droppedCount?, radius }`
- New `getCrop` accessor (returns `CropConfig | null`) renders two new sub-layers:
  - `live-crops` — spheres placed in the outer 90–102 % shell of the canopy
    ellipsoid (equatorial band only, never on crown or base)
  - `dropped-crops` — uniform-disk ground scatter within canopy footprint,
    rendered at 45 % opacity for a fallen/weathered look
- Crop positions are seeded deterministically from each tree's lng/lat via
  splitmix32 so they are stable across re-renders and sizeScale changes
- `sizeScale` applied to crop sphere radius in lock-step with all other dims

### Organic canopy geometry (tree-geometry.ts)
- `jitterSmooth()`: per-species smooth low-frequency sinusoidal vertex
  displacement (4 waves, 2–5 cycles per axis) — no mesh gaps, zero runtime cost
  - oak ±18 %, cherry ±20 %, birch ±14 %, palm ±10 %
- Pine tiers: per-tier radius ±20 %, height ±15 %, lateral drift that
  increases from zero at the bottom tier (clean trunk join) to ±0.10 units
  at the top (windswept silhouette)

### Per-tree variety (tree-layer.ts)
- `getOrientation [0, angle, 0]`: position-derived yaw (vertical-axis bearing)
  so pine tiers face different compass directions per tree
- Asymmetric XY canopy scale ±15 % from position hash: every canopy is a
  unique oval, never a perfect circle in plan view
- Both are zero extra draw calls — pure GPU instancing attributes

### Bug fixes
- Pine level→mesh bug: previously all pine instances used the first level's
  mesh; now one sub-layer is created per branch-level count with filtered data
- `CANOPY_TRUNK_OVERLAP` increased 0.10→0.22: canopy base embeds 22 % of
  canopy height into trunk, reliably hiding the trunk-top disk
- `updateTriggers` added to trunk and canopy sub-layers so sizeScale slider
  correctly invalidates `getScale` attribute buffers
- Crop phi clamped to equatorial band (cosPhi in [-0.80, 0.80]) so crops
  never appear on the canopy crown

### Wild-forest example
- 9 forest zones including citrus orchard and almond grove with crop configs
- `showCrops` checkbox toggle + `sizeScale` slider
- `vite.config.ts` aliases `@deck.gl-community/three` to TypeScript source
  for instant HMR without dist rebuild

### Docs
- README fully updated with `CropConfig` type reference, crop placement
  details, updated feature list, and wild-forest example instructions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@charlieforward9 charlieforward9 force-pushed the feat/tree-layer-oak-canopy branch from b074a48 to 18779ef Compare February 28, 2026 18:43
@charlieforward9 charlieforward9 merged commit 436af38 into master Feb 28, 2026
1 check passed
@charlieforward9 charlieforward9 deleted the feat/tree-layer-oak-canopy branch February 28, 2026 18:51
@charlieforward9 charlieforward9 restored the feat/tree-layer-oak-canopy branch February 28, 2026 18:52
@charlieforward9 charlieforward9 deleted the feat/tree-layer-oak-canopy branch February 28, 2026 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant