meat/game/actors/Tree.ts

55 lines
2.3 KiB
TypeScript
Raw Normal View History

import type { Vec3 } from "../../engine/math/Vec3"
import type { Mesh } from "../../engine/scene/Mesh"
2026-08-07 19:11:43 +02:00
import { oak } from "./trees/Oak"
import { spruce } from "./trees/Spruce"
import { birch } from "./trees/Birch"
2026-08-04 13:53:59 +02:00
2026-08-07 19:11:43 +02:00
export type TreeKind = "oak" | "spruce" | "birch"
2026-08-04 13:53:59 +02:00
2026-08-07 19:11:43 +02:00
/** One procedural tree instance. `growth` 0..1 runs sapling -> full grown: it scales
* height and girth and adds canopy blobs / tiers. `seed` drives the per-tree random
* wobble so a forest doesn't look cloned. */
2026-08-04 13:53:59 +02:00
export type Tree = {
2026-08-07 19:11:43 +02:00
kind: TreeKind
2026-08-04 13:53:59 +02:00
/** Trunk base, sitting on the ground. */
position: Vec3
growth: number
seed: number
}
2026-08-07 19:11:43 +02:00
/** Definition of a tree species: which chunk materials its trunk + foliage bake
* into, plus how to append its geometry. Each lives in its own `trees/<Kind>.ts`
* module (silhouette carries the species read); this file just assembles them.
* `trunk`/`foliage` are chunk-material keys (see `level.ts` `ChunkMaterials`):
* oak/spruce use the brown `bark`, birch the white `birch`; foliage is the oak
* `leaf` or spruce `needle`. */
export type TreeSpecies = {
kind: TreeKind
trunk: string
foliage: string
build: (tree: Tree, trunk: Mesh, foliage: Mesh, lod: "full" | "impostor") => void
}
2026-08-04 13:53:59 +02:00
2026-08-07 19:11:43 +02:00
/** All tree species (also the placement roll's palette). Trees are baked at load,
* not shipped per frame, so this order isn't an id contract like `MOB_KINDS` -- but
* keeping it lets placement + tests stay registry-driven. */
export const TREE_KINDS: TreeKind[] = ["oak", "spruce", "birch"]
2026-08-04 13:53:59 +02:00
2026-08-07 19:11:43 +02:00
/** The per-species definitions, one module each. Imported (not cloned) wherever
* used, so it works the same on the main thread and in workers. */
const SPECIES: Record<TreeKind, TreeSpecies> = { oak, spruce, birch }
2026-08-04 13:53:59 +02:00
2026-08-07 19:11:43 +02:00
export namespace Tree {
/** The species definition for a kind (its trunk/foliage materials + geometry). */
export function species(kind: TreeKind): TreeSpecies {
return SPECIES[kind]
2026-08-04 13:53:59 +02:00
}
2026-08-07 19:11:43 +02:00
/** Append one tree into the caller-provided `trunk` + `foliage` meshes (which the
* caller selects from the species' `trunk`/`foliage` material keys). `lod`
* "impostor" bakes a much cheaper stand-in for far chunks; "full" is up close. */
export function build(tree: Tree, trunk: Mesh, foliage: Mesh, lod: "full" | "impostor" = "full"): void {
SPECIES[tree.kind].build(tree, trunk, foliage, lod)
2026-08-04 13:53:59 +02:00
}
}