feat: bees and frogs
This commit is contained in:
parent
46e7070b6b
commit
16f205babe
13 changed files with 540 additions and 31 deletions
|
|
@ -4,8 +4,9 @@ import { Rasterizer } from "../engine/render/Rasterizer"
|
|||
import type { RenderConfig } from "../engine/render/RenderConfig"
|
||||
import { Sky, type SkyConfig } from "../engine/render/Sky"
|
||||
import type { Camera } from "../engine/scene/Camera"
|
||||
import type { Mat4 } from "../engine/math/Mat4"
|
||||
import { Mat4 } from "../engine/math/Mat4"
|
||||
import type { Mesh } from "../engine/scene/Mesh"
|
||||
import { Mob, type MobKind } from "../engine/scene/Mob"
|
||||
import { Sprite } from "../engine/scene/Sprite"
|
||||
import type { Vec2 } from "../engine/math/Vec2"
|
||||
import type { Vec3 } from "../engine/math/Vec3"
|
||||
|
|
@ -21,10 +22,22 @@ export type Scene = {
|
|||
walls: Mesh
|
||||
crate: Mesh
|
||||
npc: { position: Vec3; size: Vec2 }
|
||||
/** Canonical local-space mob meshes, one per kind, built once + shared by every
|
||||
* instance (each instance differs only by its per-frame model matrix). */
|
||||
mobMesh: { frog: Mesh; bee: Mesh }
|
||||
/** How many mobs the sim has -- sizes the worker's shared transform buffer. */
|
||||
mobCount: number
|
||||
sky: SkyConfig
|
||||
textures: Textures
|
||||
}
|
||||
|
||||
/** One mob's live transform for a frame: which mesh + where/how to place it.
|
||||
* Produced by `visibleMobs` on the main thread, then either passed straight to
|
||||
* `renderBand` (single-thread) or packed into the shared `mobState` buffer and
|
||||
* rebuilt in each worker. `MOB_FLOATS` is that packed layout's stride. */
|
||||
export type MobDraw = { kind: MobKind; x: number; y: number; z: number; heading: number; scale: number }
|
||||
export const MOB_FLOATS = 6 // kind(0/1), x, y, z, heading, scale
|
||||
|
||||
/** Chunk indices whose bounding box is inside the view frustum. Computed once on
|
||||
* the main thread and shared with every worker (so they don't each re-cull). */
|
||||
export function visibleChunks(chunks: Chunk[], viewProj: Mat4): number[] {
|
||||
|
|
@ -39,6 +52,24 @@ export function visibleChunks(chunks: Chunk[], viewProj: Mat4): number[] {
|
|||
return out
|
||||
}
|
||||
|
||||
/** The `MobDraw`s for mobs whose world AABB is inside the view frustum. Mobs move,
|
||||
* so (unlike chunks) they can't be baked into the culled world -- they're culled
|
||||
* here per frame instead. Computed once on the main thread; the visible set is
|
||||
* what gets shipped to the workers. */
|
||||
export function visibleMobs(mobs: Mob[], viewProj: Mat4): MobDraw[] {
|
||||
const frustum = Frustum.fromViewProj(viewProj)
|
||||
const out: MobDraw[] = []
|
||||
for (const m of mobs) {
|
||||
const r = Mob.boundingRadius(m.kind) * m.scale
|
||||
const h = Mob.bodyHeight(m.kind) * m.scale
|
||||
const p = m.position
|
||||
if (Frustum.intersectsAabb(frustum, p.x - r, p.y - r, p.z - r, p.x + r, p.y + h + r, p.z + r)) {
|
||||
out.push({ kind: m.kind, x: p.x, y: p.y, z: p.z, heading: m.heading, scale: m.scale })
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
/**
|
||||
* Render rows [y0, y1) of one frame into `fb`. This is the single source of
|
||||
* render truth: the single-thread path calls it with the full height, and each
|
||||
|
|
@ -51,6 +82,7 @@ export function renderBand(
|
|||
camera: Camera,
|
||||
viewProj: Mat4,
|
||||
visible: number[],
|
||||
mobDraws: MobDraw[],
|
||||
config: RenderConfig,
|
||||
skyStep: number,
|
||||
time: number,
|
||||
|
|
@ -84,6 +116,15 @@ export function renderBand(
|
|||
}
|
||||
const sprite: Sprite = { position: scene.npc.position, size: scene.npc.size, texture: tx.npc }
|
||||
Rasterizer.draw(fb, Sprite.billboard(sprite, camera), tx.npc, viewProj, config, false, y0, y1)
|
||||
// Roaming mobs: each is the shared local-space mesh for its kind, placed by its
|
||||
// own model matrix (viewProj x model). Drawn double-sided (cull off) -- they're
|
||||
// small and few, so the winding-correct backface cull isn't worth the fuss.
|
||||
for (const m of mobDraws) {
|
||||
const mesh = m.kind === "bee" ? scene.mobMesh.bee : scene.mobMesh.frog
|
||||
const texture = m.kind === "bee" ? tx.bee : tx.frog
|
||||
const mvp = Mat4.multiply(viewProj, Mat4.compose(m.x, m.y, m.z, m.heading, m.scale))
|
||||
Rasterizer.draw(fb, mesh, texture, mvp, config, false, y0, y1)
|
||||
}
|
||||
Framebuffer.quantize(fb, config, y0, y1)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue