refactor: move world concepts into engine

This commit is contained in:
Toad 2026-08-24 15:17:53 +02:00
parent eeedcb8e48
commit 2d15c7ab8d
52 changed files with 3298 additions and 1558 deletions

View file

@ -1,14 +1,48 @@
import { Vec3 } from "../../../engine/math/Vec3"
import type { Mesh } from "../../../engine/scene/Mesh"
import type { Tree, TreeSpecies } from "../Tree"
import type { Material } from "../../../engine/render/Material"
import type { Prefab } from "../../../engine/scene/Prefab"
import type { Tree } from "../Tree"
import { blob, lerp, limb, TAU, rng } from "./treekit"
// Oak: short tapered trunk, a couple of branches, a broad cluster of rounded canopy
// blobs (bushy, wider than tall). Trunk = brown bark, foliage = oak leaf.
export const oak: TreeSpecies = { kind: "oak", trunk: "bark", foliage: "leaf", build }
export type Oak = Prefab<Tree>
function build(tree: Tree, trunk: Mesh, leaves: Mesh, lod: "full" | "impostor"): void {
export namespace Oak {
export function create(trunk: Material, foliage: Material): Oak {
return {
position: (tree) => tree.position,
bakeNear: (tree, batch) =>
build(tree, batch.mesh(trunk), batch.mesh(foliage), "full"),
bakeFar: (tree, batch) =>
build(tree, batch.mesh(trunk), batch.mesh(foliage), "impostor"),
collider(tree) {
if (tree.growth <= 0.35) {
return null
}
const radius = tree.growth * 0.3 + 0.15
return {
shape: "box",
minX: tree.position.x - radius,
maxX: tree.position.x + radius,
minZ: tree.position.z - radius,
maxZ: tree.position.z + radius,
top: tree.position.y + 3,
standable: false,
}
},
}
}
}
function build(
tree: Tree,
trunk: Mesh,
leaves: Mesh,
lod: "full" | "impostor",
): void {
const base = tree.position
const g = tree.growth
const rand = rng(tree.seed)
@ -19,7 +53,14 @@ function build(tree: Tree, trunk: Mesh, leaves: Mesh, lod: "full" | "impostor"):
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)
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
}
@ -43,7 +84,11 @@ function build(tree: Tree, trunk: Mesh, leaves: Mesh, lod: "full" | "impostor"):
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: 1.2, z: Math.sin(angle) })
const dir = Vec3.normalize({
x: Math.cos(angle),
y: 1.2,
z: Math.sin(angle),
})
const start = { x: base.x, y: base.y + h * 0.42, z: base.z }
const end = Vec3.add(start, Vec3.scale(dir, h * 0.3))
limb(trunk, start, end, rTrunk * 0.4, rTrunk * 0.2, 4)