feat: birch
This commit is contained in:
parent
16f205babe
commit
a4490f7a20
11 changed files with 110 additions and 24 deletions
|
|
@ -7,7 +7,7 @@ const TAU = Math.PI * 2
|
|||
* scales height and girth and adds canopy blobs (oak) / tiers (spruce). `seed`
|
||||
* drives the per-tree random wobble so a forest doesn't look cloned. */
|
||||
export type Tree = {
|
||||
kind: "oak" | "spruce"
|
||||
kind: "oak" | "spruce" | "birch"
|
||||
/** Trunk base, sitting on the ground. */
|
||||
position: Vec3
|
||||
growth: number
|
||||
|
|
@ -34,8 +34,10 @@ export namespace Tree {
|
|||
const rand = rng(tree.seed)
|
||||
if (tree.kind === "oak") {
|
||||
oak(tree.position, tree.growth, rand, trunk, foliage, lod)
|
||||
} else {
|
||||
} else if (tree.kind === "spruce") {
|
||||
spruce(tree.position, tree.growth, rand, trunk, foliage, lod)
|
||||
} else {
|
||||
birch(tree.position, tree.growth, rand, trunk, foliage, lod)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,6 +103,48 @@ export namespace Tree {
|
|||
}
|
||||
}
|
||||
|
||||
function birch(base: Vec3, g: number, rand: () => number, trunk: Mesh, leaves: Mesh, lod: "full" | "impostor"): void {
|
||||
// Silver birch: tall, slender, near-straight white trunk under an airy, high,
|
||||
// slightly drooping canopy of small leaf tufts -- a lean silhouette between the
|
||||
// broad oak and the conical spruce (the white bark texture does the rest).
|
||||
const h = lerp(1, 8.5, g)
|
||||
const rTrunk = lerp(0.03, 0.16, g)
|
||||
const canopyY = base.y + h * 0.75
|
||||
const blobR = h * 0.22
|
||||
if (lod === "impostor") {
|
||||
limb(trunk, base, { x: base.x, y: base.y + h * 0.9, z: base.z }, rTrunk, rTrunk * 0.5, 3)
|
||||
blob(leaves, { x: base.x, y: canopyY, z: base.z }, blobR * 1.1, rand, 4, 2)
|
||||
return
|
||||
}
|
||||
limb(trunk, base, { x: base.x, y: base.y + h * 0.88, z: base.z }, rTrunk, rTrunk * 0.35, 5)
|
||||
|
||||
const spread = h * 0.22
|
||||
// Sparse small blobs clustered high, biased downward so the crown droops.
|
||||
const blobs = 2 + Math.round(g * 2)
|
||||
for (let i = 0; i < blobs; i++) {
|
||||
const angle = rand() * TAU
|
||||
const rad = i === 0 ? 0 : spread * (0.5 + rand() * 0.5)
|
||||
const center = {
|
||||
x: base.x + Math.cos(angle) * rad,
|
||||
y: canopyY + (rand() - 0.6) * spread,
|
||||
z: base.z + Math.sin(angle) * rad,
|
||||
}
|
||||
blob(leaves, center, blobR * (0.7 + rand() * 0.4), rand)
|
||||
}
|
||||
// Grown birches trail a few thin, near-horizontal drooping twigs.
|
||||
if (g > 0.5) {
|
||||
const branches = 2 + Math.round(rand())
|
||||
for (let i = 0; i < branches; i++) {
|
||||
const angle = rand() * TAU
|
||||
const dir = Vec3.normalize({ x: Math.cos(angle), y: 0.6, z: Math.sin(angle) })
|
||||
const start = { x: base.x, y: base.y + h * 0.7, z: base.z }
|
||||
const end = Vec3.add(start, Vec3.scale(dir, h * 0.22))
|
||||
limb(trunk, start, end, rTrunk * 0.4, rTrunk * 0.15, 4)
|
||||
blob(leaves, end, blobR * 0.55, rand)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** A tapered tube between two points (trunk or branch), `sides`-gonal. */
|
||||
function limb(mesh: Mesh, a: Vec3, b: Vec3, ra: number, rb: number, sides: number): void {
|
||||
const axis = Vec3.normalize(Vec3.sub(b, a))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue