Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

@deck.gl-community/three

NPM Version NPM Downloads

A collection of deck.gl layers powered by Three.js, giving access to Three.js geometry primitives and scene graph tooling directly inside deck.gl visualisations.

TreeLayer is the first layer in this module — a fully parametric 3D tree renderer backed by Three.js BufferGeometry and rendered via deck.gl's SimpleMeshLayer.

Layers

Layer Description
TreeLayer Procedural 3D trees with 5 species silhouettes, season colours, and crop/fruit visualisation

TreeLayer

Renders richly configurable 3D trees at geographic positions using procedural geometry generated with Three.js BufferGeometry primitives.

Features

  • 5 tree species / silhouettes: pine (tiered cones), oak (sphere), palm (flat crown), birch (narrow oval), cherry (round sphere)
  • Organic canopy geometry: smooth low-frequency vertex jitter baked into each species mesh at init time — no runtime cost, no mesh gaps
  • Per-tree variety: position-derived random bearing and asymmetric XY scale give every instance a unique silhouette with zero extra draw calls
  • Parametric geometry: per-instance height, trunk-to-canopy ratio, trunk radius, canopy radius
  • Season-driven colours: spring / summer / autumn / winter palettes with species-specific defaults
  • Explicit colour overrides: getTrunkColor and getCanopyColor accessors for full control
  • Pine tier density: getBranchLevels (1–5) controls the number of overlapping cone tiers; each tier drifts progressively for a windswept look
  • Crop / fruit / flower visualisation: getCrop places coloured spheres in the outer canopy volume and scattered on the ground beneath the tree
  • Global scale factor: sizeScale multiplier for easy zoom-level adjustment

Install

npm install @deck.gl-community/three
# or
yarn add @deck.gl-community/three

Three.js is a peer dependency pulled in automatically.

Usage

import {TreeLayer} from '@deck.gl-community/three';
import type {CropConfig} from '@deck.gl-community/three';

const layer = new TreeLayer({
  id: 'trees',
  data: myForestData,
  getPosition: d => d.coordinates,
  getTreeType: d => d.species,        // 'pine' | 'oak' | 'palm' | 'birch' | 'cherry'
  getHeight: d => d.heightMetres,
  getTrunkRadius: d => d.trunkRadius,
  getCanopyRadius: d => d.canopyRadius,
  getTrunkHeightFraction: d => 0.35,
  getSeason: d => 'autumn',
  getCrop: d => d.crop,               // CropConfig | null
  sizeScale: 1,
  pickable: true,
});

Crop / fruit / flower example

import type {CropConfig} from '@deck.gl-community/three';

// Orange orchard
const citrusCrop: CropConfig = {
  color: [255, 140, 0, 255],  // orange
  count: 30,                  // live fruits in canopy
  droppedCount: 10,           // fallen fruits on ground (rendered at 45% opacity)
  radius: 0.12,               // metres per fruit sphere (scaled by sizeScale)
};

// Cherry blossom (flowering stage — just use flower colour)
const blossomCrop: CropConfig = {
  color: [255, 200, 220, 200],
  count: 25,
  droppedCount: 8,
  radius: 0.07,
};

Crop positions are seeded deterministically from each tree's geographic coordinates, so they are stable across re-renders and sizeScale changes.


TreeLayer Props

Geometry

Prop Type Default Description
getPosition accessor → [lon, lat] d.position Tree base position
getElevation accessor → number 0 Base elevation in metres
getTreeType accessor → TreeType 'pine' Silhouette variant
getHeight accessor → number 10 Total height (metres)
getTrunkHeightFraction accessor → number 0.35 Fraction of total height occupied by trunk (0–1)
getTrunkRadius accessor → number 0.5 Trunk base radius (metres)
getCanopyRadius accessor → number 3 Canopy horizontal radius (metres)
getBranchLevels accessor → number 3 Pine tier count (1–5)
sizeScale number 1 Global size multiplier applied to all dimensions

Colour

Prop Type Default Description
getTrunkColor accessor → Color|null null Explicit trunk RGBA; null uses species default
getCanopyColor accessor → Color|null null Explicit canopy RGBA; null uses season default
getSeason accessor → Season 'summer' Drives default canopy colour when no explicit colour is given

Crops

Prop Type Default Description
getCrop accessor → CropConfig|null null Crop configuration per tree. null renders no crops

Types

TreeType

type TreeType = 'pine' | 'oak' | 'palm' | 'birch' | 'cherry';

Season

type Season = 'spring' | 'summer' | 'autumn' | 'winter';

CropConfig

Configuration for crop/fruit/flower visualisation on a single tree.

type CropConfig = {
  /** Colour of each crop sphere [r, g, b, a]. */
  color: Color;

  /** Number of crop spheres placed in the outer canopy volume (live / in-tree). */
  count: number;

  /**
   * Number of crop spheres scattered on the ground within the canopy footprint
   * (dropped / fallen). Rendered at ~45 % opacity relative to `color`.
   * @default 0
   */
  droppedCount?: number;

  /**
   * Radius of each individual crop sphere in metres (scaled by `sizeScale`).
   * Typical values: 0.06–0.15 m for fruit, 0.05–0.10 m for nuts/blossoms.
   */
  radius: number;
};

Crop placement details

  • Live crops are placed on the outer 90–102 % of the canopy ellipsoid surface (equatorial band only — never on the crown or base) so they appear nestled into the canopy with tips just visible.
  • Dropped crops are scattered uniformly across the ground disk within the canopy footprint at a fixed slight elevation (0.05 m), rendered semi-transparent.
  • All positions are derived deterministically from the tree's geographic coordinates via a seeded PRNG, so they are stable across re-renders and sizeScale changes.

Default canopy colours

Species Spring Summer Autumn Winter
pine [34, 100, 34] [0, 64, 0] [0, 64, 0] [0, 55, 0]
oak [100, 180, 80] [34, 120, 15] [180, 85, 20] [100, 80, 60] (α 160)
palm [50, 160, 50] [20, 145, 20] [55, 150, 30] [40, 130, 30]
birch [150, 210, 110] [80, 160, 60] [230, 185, 40] [180, 180, 170] (α 90)
cherry [255, 180, 205] [50, 140, 50] [200, 60, 40] [120, 90, 80] (α 110)

Wild-Forest example

A full demo with 9 forest zones (pines, oaks, palms, birches, cherry blossoms, citrus orchards, almond groves) is available at examples/three/wild-forest/.

cd examples/three/wild-forest
yarn          # first time only
yarn start    # opens http://localhost:8080

The example includes a live sizeScale slider, a crop toggle, and a zone legend.