feat: threads
This commit is contained in:
parent
6fb46573da
commit
46e7070b6b
18 changed files with 878 additions and 125 deletions
|
|
@ -28,24 +28,32 @@ export type Tree = {
|
|||
export namespace Tree {
|
||||
/** Append one tree into the shared `trunk` (bark) mesh and the `foliage` mesh
|
||||
* for its kind (oak leaf vs spruce needle). */
|
||||
export function build(tree: Tree, trunk: Mesh, foliage: Mesh): void {
|
||||
/** `lod` "impostor" bakes a much cheaper stand-in (few tris, same textures +
|
||||
* faceted look, same height/position) for far chunks; "full" is up close. */
|
||||
export function build(tree: Tree, trunk: Mesh, foliage: Mesh, lod: "full" | "impostor" = "full"): void {
|
||||
const rand = rng(tree.seed)
|
||||
if (tree.kind === "oak") {
|
||||
oak(tree.position, tree.growth, rand, trunk, foliage)
|
||||
oak(tree.position, tree.growth, rand, trunk, foliage, lod)
|
||||
} else {
|
||||
spruce(tree.position, tree.growth, rand, trunk, foliage)
|
||||
spruce(tree.position, tree.growth, rand, trunk, foliage, lod)
|
||||
}
|
||||
}
|
||||
|
||||
function oak(base: Vec3, g: number, rand: () => number, trunk: Mesh, leaves: Mesh): void {
|
||||
function oak(base: Vec3, g: number, rand: () => number, trunk: Mesh, leaves: Mesh, lod: "full" | "impostor"): void {
|
||||
const h = lerp(0.8, 7, g)
|
||||
const rTrunk = lerp(0.04, 0.32, g)
|
||||
const forkY = base.y + h * 0.5
|
||||
const canopyY = base.y + h * 0.72
|
||||
const blobR = h * 0.3
|
||||
if (lod === "impostor") {
|
||||
// One low-poly blob on a stubby trunk -- reads as an oak at distance.
|
||||
limb(trunk, base, { x: base.x, y: forkY, z: base.z }, rTrunk, rTrunk * 0.6, 3)
|
||||
blob(leaves, { x: base.x, y: canopyY, z: base.z }, blobR * 1.15, rand, 4, 2)
|
||||
return
|
||||
}
|
||||
limb(trunk, base, { x: base.x, y: forkY, z: base.z }, rTrunk, rTrunk * 0.6, 5)
|
||||
|
||||
const blobR = h * 0.3
|
||||
const spread = h * 0.32
|
||||
const canopyY = base.y + h * 0.72
|
||||
// Central blob plus, as it grows, a couple offset ones -> broad bushy crown.
|
||||
const blobs = 1 + Math.round(g * 2)
|
||||
for (let i = 0; i < blobs; i++) {
|
||||
|
|
@ -72,13 +80,16 @@ export namespace Tree {
|
|||
}
|
||||
}
|
||||
|
||||
function spruce(base: Vec3, g: number, rand: () => number, trunk: Mesh, needles: Mesh): void {
|
||||
function spruce(base: Vec3, g: number, rand: () => number, trunk: Mesh, needles: Mesh, lod: "full" | "impostor"): void {
|
||||
const h = lerp(0.6, 9, g)
|
||||
const rTrunk = lerp(0.03, 0.2, g)
|
||||
limb(trunk, base, { x: base.x, y: base.y + h, z: base.z }, rTrunk, rTrunk * 0.25, 5)
|
||||
const impostor = lod === "impostor"
|
||||
limb(trunk, base, { x: base.x, y: base.y + h, z: base.z }, rTrunk, rTrunk * 0.25, impostor ? 3 : 5)
|
||||
|
||||
// Stacked cones: widest low, shrinking to a point up top -> conical tiers.
|
||||
const tiers = 2 + Math.round(g * 3)
|
||||
// The impostor keeps the first two tiers at low sides (same seed => aligned).
|
||||
const tiers = impostor ? 2 : 2 + Math.round(g * 3)
|
||||
const sides = impostor ? 4 : 6
|
||||
const bottom = base.y + h * 0.1
|
||||
const span = h * 0.9
|
||||
for (let i = 0; i < tiers; i++) {
|
||||
|
|
@ -86,7 +97,7 @@ export namespace Tree {
|
|||
const y = bottom + t * span * 0.82
|
||||
const radius = lerp(h * 0.3, h * 0.05, t) * (0.9 + rand() * 0.2)
|
||||
const coneH = (span / tiers) * 1.9
|
||||
cone(needles, { x: base.x, y, z: base.z }, coneH, radius, 6)
|
||||
cone(needles, { x: base.x, y, z: base.z }, coneH, radius, sides)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -127,9 +138,7 @@ export namespace Tree {
|
|||
|
||||
/** A lumpy low-poly sphere (one oak canopy blob). Per-ring radius wobble keeps
|
||||
* it organic without cracking the longitude seam. */
|
||||
function blob(mesh: Mesh, center: Vec3, radius: number, rand: () => number): void {
|
||||
const seg = 5
|
||||
const rings = 3
|
||||
function blob(mesh: Mesh, center: Vec3, radius: number, rand: () => number, seg = 5, rings = 3): void {
|
||||
const start = mesh.verts.length / STRIDE
|
||||
for (let r = 0; r <= rings; r++) {
|
||||
const phi = (r / rings) * Math.PI
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue