@adatechnology/game-fluids-three 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +105 -2
- package/dist/index.d.ts +68 -0
- package/dist/index.global.js +1117 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +1081 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/clip.ts","../src/liquid-body.ts","../src/util.ts","../src/materials.ts","../src/particles.ts","../src/quality.ts","../src/stains.ts","../src/streams.ts","../src/renderer.ts"],"sourcesContent":["/**\n * Convex solids (a cylinder or a box, in container space) clipped by the liquid surface plane `u · p <= d`.\n * This is robust for any tilt (upright, lying on its side, upside down): the result is exactly the part of the container the liquid fills,\n * with the surface cap lying on the plane. Written into preallocated buffers, no per-frame geometry is created.\n */\nexport type V3 = [number, number, number]\n\nexport interface SolidFace {\n p: V3[]\n n: V3[]\n}\n\nexport interface Solid {\n faces: SolidFace[]\n /** Upper bound of the vertices a clip can write (non-indexed triangles). */\n maxVertices: number\n}\n\nconst sub = (a: V3, b: V3): V3 => [a[0] - b[0], a[1] - b[1], a[2] - b[2]]\nconst cross = (a: V3, b: V3): V3 => [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]]\nconst dot = (a: V3, b: V3): number => a[0] * b[0] + a[1] * b[1] + a[2] * b[2]\nconst norm = (a: V3): V3 => {\n const l = Math.hypot(a[0], a[1], a[2]) || 1\n return [a[0] / l, a[1] / l, a[2] / l]\n}\n\n/** Reverse the winding when the face does not look outward. */\nconst orient = (p: V3[], n: V3[], outward: V3): SolidFace => {\n if (dot(cross(sub(p[1], p[0]), sub(p[2], p[0])), outward) < 0) return { p: [...p].reverse(), n: [...n].reverse() }\n return { p, n }\n}\n\nconst finish = (faces: SolidFace[]): Solid => {\n let maxVertices = 0\n for (const f of faces) maxVertices += (f.p.length * 2 + 2) * 3\n // The surface cap: at most one point per face edge cut.\n maxVertices += faces.length * 3 * 2 + 64\n return { faces, maxVertices }\n}\n\nexport const cylinderSolid = (radius: number, height: number, segments: number): Solid => {\n const faces: SolidFace[] = []\n const ring = (y: number, i: number): V3 => {\n const a = (i / segments) * Math.PI * 2\n return [Math.cos(a) * radius, y, Math.sin(a) * radius]\n }\n const radial = (i: number): V3 => {\n const a = (i / segments) * Math.PI * 2\n return [Math.cos(a), 0, Math.sin(a)]\n }\n for (let i = 0; i < segments; i++) {\n const j = (i + 1) % segments\n const mid = norm([radial(i)[0] + radial(j)[0], 0, radial(i)[2] + radial(j)[2]])\n faces.push(orient([ring(0, i), ring(0, j), ring(height, j), ring(height, i)], [radial(i), radial(j), radial(j), radial(i)], mid))\n }\n const bottom: V3[] = []\n const top: V3[] = []\n for (let i = 0; i < segments; i++) {\n bottom.push(ring(0, i))\n top.push(ring(height, i))\n }\n faces.push(orient(bottom, bottom.map((): V3 => [0, -1, 0]), [0, -1, 0]))\n faces.push(orient(top, top.map((): V3 => [0, 1, 0]), [0, 1, 0]))\n return finish(faces)\n}\n\nexport const boxSolid = (size: V3): Solid => {\n const hx = size[0] / 2\n const hz = size[2] / 2\n const hy = size[1]\n const c = (x: number, y: number, z: number): V3 => [x * hx, y * hy, z * hz]\n const quad = (a: V3, b: V3, cc: V3, d: V3, n: V3): SolidFace => orient([a, b, cc, d], [n, n, n, n], n)\n return finish([\n quad(c(1, 0, -1), c(1, 1, -1), c(1, 1, 1), c(1, 0, 1), [1, 0, 0]),\n quad(c(-1, 0, -1), c(-1, 1, -1), c(-1, 1, 1), c(-1, 0, 1), [-1, 0, 0]),\n quad(c(-1, 1, -1), c(1, 1, -1), c(1, 1, 1), c(-1, 1, 1), [0, 1, 0]),\n quad(c(-1, 0, -1), c(1, 0, -1), c(1, 0, 1), c(-1, 0, 1), [0, -1, 0]),\n quad(c(-1, 0, 1), c(1, 0, 1), c(1, 1, 1), c(-1, 1, 1), [0, 0, 1]),\n quad(c(-1, 0, -1), c(1, 0, -1), c(1, 1, -1), c(-1, 1, -1), [0, 0, -1]),\n ])\n}\n\nconst polyP: number[] = []\nconst polyN: number[] = []\nconst cut: number[] = []\n\n/**\n * Writes the triangles of `solid ∩ { u · p <= d }` into `pos` / `nor` (non-indexed, 3 floats per vertex) and returns the vertex count.\n * The cap on the plane has normal `u`.\n */\nexport const clipSolid = (solid: Solid, u: V3, d: number, pos: Float32Array, nor: Float32Array): number => {\n let count = 0\n const capacity = Math.floor(pos.length / 3)\n cut.length = 0\n const put = (px: number, py: number, pz: number, nx: number, ny: number, nz: number): void => {\n if (count >= capacity) return\n pos[count * 3] = px\n pos[count * 3 + 1] = py\n pos[count * 3 + 2] = pz\n nor[count * 3] = nx\n nor[count * 3 + 1] = ny\n nor[count * 3 + 2] = nz\n count++\n }\n\n for (const face of solid.faces) {\n const m = face.p.length\n polyP.length = 0\n polyN.length = 0\n for (let i = 0; i < m; i++) {\n const a = face.p[i]\n const b = face.p[(i + 1) % m]\n const na = face.n[i]\n const nb = face.n[(i + 1) % m]\n const da = u[0] * a[0] + u[1] * a[1] + u[2] * a[2] - d\n const db = u[0] * b[0] + u[1] * b[1] + u[2] * b[2] - d\n const ina = da <= 0\n const inb = db <= 0\n if (ina) {\n polyP.push(a[0], a[1], a[2])\n polyN.push(na[0], na[1], na[2])\n if (da > -1e-7) cut.push(a[0], a[1], a[2])\n }\n if (ina !== inb) {\n const t = da / (da - db)\n const x = a[0] + (b[0] - a[0]) * t\n const y = a[1] + (b[1] - a[1]) * t\n const z = a[2] + (b[2] - a[2]) * t\n polyP.push(x, y, z)\n polyN.push(na[0] + (nb[0] - na[0]) * t, na[1] + (nb[1] - na[1]) * t, na[2] + (nb[2] - na[2]) * t)\n cut.push(x, y, z)\n }\n }\n const n = polyP.length / 3\n for (let i = 1; i < n - 1; i++) {\n for (const k of [0, i, i + 1]) put(polyP[k * 3], polyP[k * 3 + 1], polyP[k * 3 + 2], polyN[k * 3], polyN[k * 3 + 1], polyN[k * 3 + 2])\n }\n }\n\n // Cap on the plane: unique cut points sorted around their centre.\n const pts: V3[] = []\n for (let i = 0; i < cut.length; i += 3) {\n let dup = false\n for (const q of pts) {\n if (Math.abs(q[0] - cut[i]) + Math.abs(q[1] - cut[i + 1]) + Math.abs(q[2] - cut[i + 2]) < 1e-6) {\n dup = true\n break\n }\n }\n if (!dup) pts.push([cut[i], cut[i + 1], cut[i + 2]])\n }\n if (pts.length >= 3) {\n const c: V3 = [0, 0, 0]\n for (const q of pts) {\n c[0] += q[0] / pts.length\n c[1] += q[1] / pts.length\n c[2] += q[2] / pts.length\n }\n const e1 = norm(cross(u, Math.abs(u[0]) < 0.9 ? [1, 0, 0] : [0, 1, 0]))\n const e2 = cross(u, e1)\n const keyed = pts.map((q) => ({ q, a: Math.atan2(dot(sub(q, c), e2), dot(sub(q, c), e1)) })).sort((p, r) => p.a - r.a)\n for (let i = 0; i < keyed.length; i++) {\n for (const q of [c, keyed[i].q, keyed[(i + 1) % keyed.length].q]) put(q[0], q[1], q[2], u[0], u[1], u[2])\n }\n }\n return count\n}\n","import type * as THREE_NS from 'three'\nimport type { ContainerState, FluidWorld, Vec3 } from '@adatechnology/game-fluids'\nimport { boxSolid, clipSolid, cylinderSolid } from './clip'\nimport type { Solid, V3 } from './clip'\nimport type { MaterialCache } from './materials'\nimport type { ParticlePool } from './particles'\nimport type { QualityProfile } from './quality'\nimport type { ThreeLib } from './types'\n\n/** How far the liquid is kept inside the container walls so it does not fight with them. */\nconst INSET = 0.985\n\n/**\n * The liquid inside one bound container: the container's inner shape clipped by the world surface plane, expressed in the bound object's space,\n * so the cap always lies on the plane whatever the tilt. Plus steam puffs above a hot surface.\n */\nexport class LiquidBody {\n readonly group: THREE_NS.Group\n private mesh: THREE_NS.Mesh | null = null\n private geometry: THREE_NS.BufferGeometry | null = null\n private pos: Float32Array = new Float32Array(0)\n private nor: Float32Array = new Float32Array(0)\n private solid: Solid | null = null\n private shapeKey = ''\n private steamAcc = 0\n private readonly inverse: THREE_NS.Matrix4\n private readonly tmpN: THREE_NS.Vector3\n private readonly tmpP: THREE_NS.Vector3\n vertices = 0\n\n constructor(\n private readonly THREE: ThreeLib,\n readonly containerId: string,\n readonly object: THREE_NS.Object3D,\n offset: Vec3,\n ) {\n this.group = new THREE.Group()\n this.group.name = 'fluid_liquid_body'\n this.group.position.set(offset[0], offset[1], offset[2])\n this.inverse = new THREE.Matrix4()\n this.tmpN = new THREE.Vector3()\n this.tmpP = new THREE.Vector3()\n object.add(this.group)\n }\n\n get visible(): boolean {\n return !!this.mesh && this.mesh.visible\n }\n\n private build(state: ContainerState, quality: QualityProfile): void {\n const shape = state.shape\n if (!shape) return\n const key = JSON.stringify(shape) + quality.bodySegments\n if (key === this.shapeKey) return\n this.shapeKey = key\n this.solid =\n shape.kind === 'cylinder'\n ? cylinderSolid(shape.radius * INSET, shape.height * INSET, quality.bodySegments)\n : boxSolid([shape.size[0] * INSET, shape.size[1] * INSET, shape.size[2] * INSET])\n const T = this.THREE\n this.geometry?.dispose()\n this.pos = new Float32Array(this.solid.maxVertices * 3)\n this.nor = new Float32Array(this.solid.maxVertices * 3)\n this.geometry = new T.BufferGeometry()\n const p = new T.BufferAttribute(this.pos, 3)\n const n = new T.BufferAttribute(this.nor, 3)\n p.setUsage(T.DynamicDrawUsage)\n n.setUsage(T.DynamicDrawUsage)\n this.geometry.setAttribute('position', p)\n this.geometry.setAttribute('normal', n)\n if (!this.mesh) {\n this.mesh = new T.Mesh(this.geometry)\n this.mesh.name = 'fluid_liquid'\n this.mesh.frustumCulled = false\n this.mesh.renderOrder = 3\n this.group.add(this.mesh)\n } else this.mesh.geometry = this.geometry\n }\n\n update(dt: number, world: FluidWorld, materials: MaterialCache, quality: QualityProfile, particles: ParticlePool): void {\n const state = world.container(this.containerId)\n const def = state?.liquid ? world.liquids.get(state.liquid) : undefined\n if (!state || !state.shape || !def || state.liters <= 1e-6) {\n if (this.mesh) this.mesh.visible = false\n this.vertices = 0\n return\n }\n this.build(state, quality)\n if (!this.mesh || !this.solid) return\n this.mesh.material = materials.liquidBody(def)\n\n // The surface plane in the group's space.\n this.object.updateWorldMatrix(true, false)\n this.group.updateWorldMatrix(true, false)\n this.inverse.copy(this.group.matrixWorld).invert()\n this.tmpN.set(state.surfaceNormal[0], state.surfaceNormal[1], state.surfaceNormal[2]).transformDirection(this.inverse)\n this.tmpP.set(state.surfacePoint[0], state.surfacePoint[1], state.surfacePoint[2]).applyMatrix4(this.inverse)\n const u: V3 = [this.tmpN.x, this.tmpN.y, this.tmpN.z]\n const d = u[0] * this.tmpP.x + u[1] * this.tmpP.y + u[2] * this.tmpP.z\n\n this.vertices = clipSolid(this.solid, u, d, this.pos, this.nor)\n const geometry = this.geometry as THREE_NS.BufferGeometry\n geometry.setDrawRange(0, this.vertices)\n ;(geometry.getAttribute('position') as THREE_NS.BufferAttribute).needsUpdate = true\n ;(geometry.getAttribute('normal') as THREE_NS.BufferAttribute).needsUpdate = true\n this.mesh.visible = this.vertices > 0\n\n // Steam above a hot open surface.\n if (state.steaming && this.vertices > 0) {\n this.steamAcc += dt * quality.steamRate\n while (this.steamAcc >= 1) {\n this.steamAcc -= 1\n const o = this.tmpP.set(state.surfacePoint[0], state.surfacePoint[1], state.surfacePoint[2])\n particles.steam([o.x, o.y + 0.01, o.z])\n }\n } else this.steamAcc = 0\n }\n\n get triangles(): number {\n return this.visible ? Math.floor(this.vertices / 3) : 0\n }\n\n dispose(): void {\n this.object.remove(this.group)\n this.geometry?.dispose()\n this.geometry = null\n this.mesh = null\n }\n}\n","export const clamp = (v: number, lo: number, hi: number): number => (v < lo ? lo : v > hi ? hi : v)\nexport const lerp = (a: number, b: number, t: number): number => a + (b - a) * t\n\n/** Small seeded generator for cosmetic randomness (droplet directions): the same input gives the same droplets. */\nexport class Rng {\n private state: number\n constructor(seed: number) {\n this.state = (seed >>> 0) || 1\n }\n next(): number {\n this.state = (this.state + 0x6d2b79f5) >>> 0\n let t = this.state\n t = Math.imul(t ^ (t >>> 15), t | 1)\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61)\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/** Integer hash of a point, to seed cosmetic randomness from world state. */\nexport const hashPoint = (x: number, y: number, z: number): number => {\n let h = 2166136261\n for (const v of [x, y, z]) h = Math.imul(h ^ Math.round(v * 1000), 16777619)\n return h >>> 0\n}\n","import type * as THREE_NS from 'three'\nimport type { LiquidDef } from '@adatechnology/game-fluids'\nimport { clamp } from './util'\nimport type { ThreeLib } from './types'\n\n/** Colour of a stain: the liquid's `stainColor`, else a darker `color`. */\nexport const stainColorOf = (def: LiquidDef): number => {\n if (def.stainColor !== undefined) return def.stainColor\n const r = ((def.color >> 16) & 255) * 0.65\n const g = ((def.color >> 8) & 255) * 0.65\n const b = (def.color & 255) * 0.65\n return (Math.round(r) << 16) | (Math.round(g) << 8) | Math.round(b)\n}\n\n/**\n * One material per liquid and role, created on demand and shared by every mesh: each liquid is its own material (colour, opacity, gloss).\n * Wet surfaces use a low roughness from `gloss` so they reflect the scene's environment.\n */\nexport class MaterialCache {\n private body = new Map<string, THREE_NS.MeshStandardMaterial>()\n private stream = new Map<string, THREE_NS.MeshStandardMaterial>()\n private film = new Map<string, THREE_NS.MeshStandardMaterial>()\n private wet = new Map<string, THREE_NS.MeshStandardMaterial>()\n\n constructor(\n private readonly THREE: ThreeLib,\n private readonly envMap: THREE_NS.Texture | null,\n ) {}\n\n private make(params: THREE_NS.MeshStandardMaterialParameters): THREE_NS.MeshStandardMaterial {\n const m = new this.THREE.MeshStandardMaterial({ metalness: 0, ...params })\n if (this.envMap) m.envMap = this.envMap\n return m\n }\n\n /** The volume of liquid inside a container. */\n liquidBody(def: LiquidDef): THREE_NS.MeshStandardMaterial {\n let m = this.body.get(def.id)\n if (!m) {\n m = this.make({\n color: def.color,\n opacity: def.opacity,\n transparent: def.opacity < 0.999,\n roughness: clamp(1 - def.gloss * 0.9, 0.04, 1),\n envMapIntensity: 0.5 + def.gloss * 0.9,\n depthWrite: def.opacity >= 0.999,\n })\n this.body.set(def.id, m)\n }\n return m\n }\n\n /** A jet or a drop in the air. */\n liquidStream(def: LiquidDef): THREE_NS.MeshStandardMaterial {\n let m = this.stream.get(def.id)\n if (!m) {\n m = this.make({\n color: def.color,\n opacity: clamp(def.opacity + 0.1, 0.35, 1),\n transparent: true,\n roughness: clamp(1 - def.gloss * 0.95, 0.03, 1),\n envMapIntensity: 0.8 + def.gloss,\n side: this.THREE.DoubleSide,\n depthWrite: false,\n })\n this.stream.set(def.id, m)\n }\n return m\n }\n\n /** The thin outer film of a stain (and the permanent mark): tinted by vertex colour, soft rim by vertex alpha, mostly matte. */\n stainFilm(def: LiquidDef): THREE_NS.MeshStandardMaterial {\n let m = this.film.get(def.id)\n if (!m) {\n m = this.make({\n color: 0xffffff,\n vertexColors: true,\n transparent: true,\n roughness: clamp(0.95 - def.gloss * 0.45, 0.3, 1),\n envMapIntensity: 0.4 + def.gloss * 0.4,\n depthWrite: false,\n polygonOffset: true,\n polygonOffsetFactor: -2,\n polygonOffsetUnits: -2,\n })\n this.film.set(def.id, m)\n }\n return m\n }\n\n /** The glossy wet part of a stain, which shrinks while it dries. */\n stainWet(def: LiquidDef): THREE_NS.MeshStandardMaterial {\n let m = this.wet.get(def.id)\n if (!m) {\n m = this.make({\n color: 0xffffff,\n vertexColors: true,\n transparent: true,\n roughness: clamp(1 - def.gloss, 0.02, 0.7),\n envMapIntensity: 0.9 + def.gloss * 1.4,\n depthWrite: false,\n polygonOffset: true,\n polygonOffsetFactor: -3,\n polygonOffsetUnits: -3,\n })\n this.wet.set(def.id, m)\n }\n return m\n }\n\n dispose(): void {\n for (const map of [this.body, this.stream, this.film, this.wet]) {\n for (const m of map.values()) m.dispose()\n map.clear()\n }\n }\n}\n","import type * as THREE_NS from 'three'\nimport { Rng, clamp, hashPoint } from './util'\nimport type { ThreeLib } from './types'\n\nconst VERTEX = /* glsl */ `\nattribute float aSize;\nattribute vec4 aColor;\nattribute float aSoft;\nuniform float uScale;\nvarying vec4 vColor;\nvarying float vSoft;\nvoid main() {\n vColor = aColor;\n vSoft = aSoft;\n vec4 mv = modelViewMatrix * vec4(position, 1.0);\n gl_PointSize = aSize * uScale / max(0.1, -mv.z);\n gl_Position = projectionMatrix * mv;\n}\n`\n\n// Round sprite drawn in the fragment shader: no textures.\nconst FRAGMENT = /* glsl */ `\nvarying vec4 vColor;\nvarying float vSoft;\nvoid main() {\n float d = length(gl_PointCoord - vec2(0.5)) * 2.0;\n if (d > 1.0 || vColor.a <= 0.001) discard;\n float edge = mix(smoothstep(1.0, 0.8, d), 1.0 - d, vSoft);\n gl_FragColor = vec4(vColor.rgb, vColor.a * edge);\n}\n`\n\n/**\n * A fixed pool of round point sprites: splash droplets (ballistic, they die on the floor they hit) and steam (soft, rising puffs).\n * One draw call. When the pool is full the oldest slot is reused.\n */\nexport class ParticlePool {\n readonly points: THREE_NS.Points\n private readonly geometry: THREE_NS.BufferGeometry\n private readonly material: THREE_NS.ShaderMaterial\n private readonly capacity: number\n private next = 0\n private readonly pos: Float32Array\n private readonly size: Float32Array\n private readonly color: Float32Array\n private readonly soft: Float32Array\n private readonly vel: Float32Array\n private readonly life: Float32Array\n private readonly maxLife: Float32Array\n private readonly size0: Float32Array\n private readonly size1: Float32Array\n private readonly alpha: Float32Array\n private readonly floorY: Float32Array\n private readonly kind: Uint8Array\n private readonly rgb: Float32Array\n private readonly rng = new Rng(1234567)\n private alive = 0\n\n constructor(\n private readonly THREE: ThreeLib,\n capacity: number,\n pointScale: number,\n ) {\n this.capacity = capacity\n this.pos = new Float32Array(capacity * 3)\n this.size = new Float32Array(capacity)\n this.color = new Float32Array(capacity * 4)\n this.soft = new Float32Array(capacity)\n this.vel = new Float32Array(capacity * 3)\n this.life = new Float32Array(capacity)\n this.maxLife = new Float32Array(capacity)\n this.size0 = new Float32Array(capacity)\n this.size1 = new Float32Array(capacity)\n this.alpha = new Float32Array(capacity)\n this.floorY = new Float32Array(capacity)\n this.kind = new Uint8Array(capacity)\n this.rgb = new Float32Array(capacity * 3)\n this.life.fill(0)\n const T = THREE\n this.geometry = new T.BufferGeometry()\n const attr = (array: Float32Array, n: number) => {\n const a = new T.BufferAttribute(array, n)\n a.setUsage(T.DynamicDrawUsage)\n return a\n }\n this.geometry.setAttribute('position', attr(this.pos, 3))\n this.geometry.setAttribute('aSize', attr(this.size, 1))\n this.geometry.setAttribute('aColor', attr(this.color, 4))\n this.geometry.setAttribute('aSoft', attr(this.soft, 1))\n this.material = new T.ShaderMaterial({\n vertexShader: VERTEX,\n fragmentShader: FRAGMENT,\n uniforms: { uScale: { value: pointScale } },\n transparent: true,\n depthWrite: false,\n })\n this.points = new T.Points(this.geometry, this.material)\n this.points.frustumCulled = false\n this.points.renderOrder = 4\n this.points.name = 'fluid_particles'\n }\n\n get count(): number {\n return this.alive\n }\n\n private slot(): number {\n const i = this.next\n this.next = (this.next + 1) % this.capacity\n return i\n }\n\n private setColor(i: number, hex: number): void {\n this.rgb[i * 3] = ((hex >> 16) & 255) / 255\n this.rgb[i * 3 + 1] = ((hex >> 8) & 255) / 255\n this.rgb[i * 3 + 2] = (hex & 255) / 255\n }\n\n /** Droplets thrown up by an impact; `floorY` is the height they stop at. */\n splash(point: [number, number, number], intensity: number, hex: number, opacity: number, count: number): void {\n const rng = new Rng(hashPoint(point[0], point[1], point[2]) ^ this.next)\n const n = Math.max(2, Math.round(count * (0.35 + 0.65 * clamp(intensity, 0, 1))))\n for (let k = 0; k < n; k++) {\n const i = this.slot()\n const a = rng.next() * Math.PI * 2\n const h = (0.25 + rng.next() * 0.9) * (0.4 + intensity)\n const up = (0.7 + rng.next() * 1.5) * (0.5 + intensity)\n this.pos.set([point[0], point[1] + 0.01, point[2]], i * 3)\n this.vel.set([Math.cos(a) * h, up, Math.sin(a) * h], i * 3)\n this.life[i] = this.maxLife[i] = 0.45 + rng.next() * 0.45\n this.size0[i] = 0.012 + rng.next() * 0.014\n this.size1[i] = this.size0[i] * 0.7\n this.alpha[i] = clamp(opacity + 0.2, 0.35, 1)\n this.soft[i] = 0\n this.kind[i] = 0\n this.floorY[i] = point[1]\n this.setColor(i, hex)\n }\n }\n\n /** One puff of steam rising from `point`. */\n steam(point: [number, number, number]): void {\n const i = this.slot()\n const r = this.rng\n this.pos.set([point[0] + (r.next() - 0.5) * 0.04, point[1], point[2] + (r.next() - 0.5) * 0.04], i * 3)\n this.vel.set([(r.next() - 0.5) * 0.06, 0.22 + r.next() * 0.12, (r.next() - 0.5) * 0.06], i * 3)\n this.life[i] = this.maxLife[i] = 1.2 + r.next() * 0.6\n this.size0[i] = 0.03\n this.size1[i] = 0.1\n this.alpha[i] = 0.24\n this.soft[i] = 1\n this.kind[i] = 1\n this.floorY[i] = -1e9\n this.setColor(i, 0xf4f8ff)\n }\n\n update(dt: number, gravity: number): void {\n let alive = 0\n for (let i = 0; i < this.capacity; i++) {\n if (this.life[i] <= 0) {\n this.size[i] = 0\n this.color[i * 4 + 3] = 0\n continue\n }\n this.life[i] -= dt\n const k = 1 - this.life[i] / this.maxLife[i]\n if (this.life[i] <= 0) {\n this.size[i] = 0\n this.color[i * 4 + 3] = 0\n continue\n }\n alive++\n if (this.kind[i] === 0) {\n this.vel[i * 3 + 1] -= gravity * dt\n } else {\n // Steam drifts sideways a little while rising.\n this.vel[i * 3] += Math.sin((k + i) * 7) * 0.02 * dt\n }\n this.pos[i * 3] += this.vel[i * 3] * dt\n this.pos[i * 3 + 1] += this.vel[i * 3 + 1] * dt\n this.pos[i * 3 + 2] += this.vel[i * 3 + 2] * dt\n if (this.kind[i] === 0 && this.pos[i * 3 + 1] < this.floorY[i]) {\n this.life[i] = 0\n alive--\n this.size[i] = 0\n this.color[i * 4 + 3] = 0\n continue\n }\n this.size[i] = this.size0[i] + (this.size1[i] - this.size0[i]) * k\n const fade = this.kind[i] === 1 ? Math.min(1, k * 4) * (1 - k) : 1 - k * k\n this.color[i * 4] = this.rgb[i * 3]\n this.color[i * 4 + 1] = this.rgb[i * 3 + 1]\n this.color[i * 4 + 2] = this.rgb[i * 3 + 2]\n this.color[i * 4 + 3] = this.alpha[i] * fade\n }\n this.alive = alive\n for (const name of ['position', 'aSize', 'aColor', 'aSoft']) (this.geometry.getAttribute(name) as THREE_NS.BufferAttribute).needsUpdate = true\n }\n\n clear(): void {\n this.life.fill(0)\n this.alive = 0\n this.update(0, 0)\n }\n\n dispose(): void {\n this.geometry.dispose()\n this.material.dispose()\n }\n}\n","import type { FluidQuality } from './types'\n\nexport interface QualityProfile {\n /** Radial segments of the container liquid volume. */\n bodySegments: number\n /** Samples along a stream and sides of its tube. */\n streamSamples: number\n streamSides: number\n /** Drops of a thin stream. */\n thinDrops: number\n /** Subdivisions per front sample of a stain outline (16 samples). */\n stainSubdiv: number\n maxStains: number\n maxStreams: number\n maxParticles: number\n /** Steam puffs per second of a steaming container. */\n steamRate: number\n /** Droplets of a full-intensity splash. */\n splashDroplets: number\n}\n\nexport const PROFILES: Record<FluidQuality, QualityProfile> = {\n low: { bodySegments: 10, streamSamples: 8, streamSides: 4, thinDrops: 4, stainSubdiv: 1, maxStains: 24, maxStreams: 12, maxParticles: 96, steamRate: 4, splashDroplets: 5 },\n medium: { bodySegments: 14, streamSamples: 12, streamSides: 5, thinDrops: 6, stainSubdiv: 2, maxStains: 48, maxStreams: 24, maxParticles: 256, steamRate: 8, splashDroplets: 9 },\n high: { bodySegments: 20, streamSamples: 20, streamSides: 8, thinDrops: 8, stainSubdiv: 4, maxStains: 96, maxStreams: 48, maxParticles: 512, steamRate: 14, splashDroplets: 14 },\n}\n\nexport const profileOf = (q: FluidQuality | undefined): QualityProfile => PROFILES[q ?? 'medium'] ?? PROFILES.medium\n","import type * as THREE_NS from 'three'\nimport { STAIN_SAMPLES } from '@adatechnology/game-fluids'\nimport type { LiquidDef, StainState, Vec3 } from '@adatechnology/game-fluids'\nimport type { MaterialCache } from './materials'\nimport { stainColorOf } from './materials'\nimport type { QualityProfile } from './quality'\nimport { clamp } from './util'\nimport type { ThreeLib } from './types'\n\n/** Periodic Catmull-Rom of the 16 front radii: a smooth outline with `subdiv` points per sample. */\nexport const smoothOutline = (front: number[], subdiv: number, out?: number[]): number[] => {\n const n = front.length\n const res = out ?? []\n res.length = n * subdiv\n for (let i = 0; i < n; i++) {\n const p0 = front[(i + n - 1) % n]\n const p1 = front[i]\n const p2 = front[(i + 1) % n]\n const p3 = front[(i + 2) % n]\n for (let j = 0; j < subdiv; j++) {\n const t = j / subdiv\n const r = 0.5 * (2 * p1 + (-p0 + p2) * t + (2 * p0 - 5 * p1 + 4 * p2 - p3) * t * t + (-p0 + 3 * p1 - 3 * p2 + p3) * t * t * t)\n res[i * subdiv + j] = Math.max(0.004, r)\n }\n }\n return res\n}\n\ninterface Fan {\n mesh: THREE_NS.Mesh\n position: Float32Array\n color: Float32Array\n}\n\n/**\n * One stain: an outer film (the whole flow-front polygon, soft at the rim) and an inner glossy fan at `wetRadius` that recedes while it dries.\n * Both are triangle fans with preallocated buffers, lying on the surface plane a hair above it.\n */\nexport class StainVisual {\n readonly group: THREE_NS.Group\n private readonly outer: Fan\n private readonly inner: Fan\n private readonly ring: number\n private readonly radii: number[] = []\n private readonly tint: THREE_NS.Color\n stainId = ''\n signature = Number.NaN\n triangles = 0\n\n constructor(\n private readonly THREE: ThreeLib,\n profile: QualityProfile,\n readonly slot: number,\n ) {\n this.ring = STAIN_SAMPLES * profile.stainSubdiv\n this.group = new THREE.Group()\n this.group.name = 'fluid_stain'\n this.tint = new THREE.Color()\n this.outer = this.makeFan('fluid_stain_film', 1)\n this.inner = this.makeFan('fluid_stain_wet', 2)\n this.group.add(this.outer.mesh, this.inner.mesh)\n this.group.visible = false\n }\n\n private makeFan(name: string, order: number): Fan {\n const T = this.THREE\n const count = 1 + this.ring\n const position = new Float32Array(count * 3)\n const color = new Float32Array(count * 4)\n const normal = new Float32Array(count * 3)\n const geometry = new T.BufferGeometry()\n const p = new T.BufferAttribute(position, 3)\n const c = new T.BufferAttribute(color, 4)\n p.setUsage(T.DynamicDrawUsage)\n c.setUsage(T.DynamicDrawUsage)\n geometry.setAttribute('position', p)\n geometry.setAttribute('normal', new T.BufferAttribute(normal, 3))\n geometry.setAttribute('color', c)\n const index: number[] = []\n for (let i = 0; i < this.ring; i++) index.push(0, 1 + i, 1 + ((i + 1) % this.ring))\n geometry.setIndex(index)\n const mesh = new T.Mesh(geometry)\n mesh.name = name\n mesh.frustumCulled = false\n mesh.renderOrder = order\n return { mesh, position, color }\n }\n\n assign(def: LiquidDef, materials: MaterialCache): void {\n this.outer.mesh.material = materials.stainFilm(def)\n this.inner.mesh.material = materials.stainWet(def)\n }\n\n hide(): void {\n this.group.visible = false\n this.stainId = ''\n this.signature = Number.NaN\n this.triangles = 0\n }\n\n /** Rebuild the vertices from the stain state (skipped when nothing changed). */\n update(stain: StainState, def: LiquidDef, profile: QualityProfile): void {\n const sig =\n stain.center[0] * 3 +\n stain.center[1] * 5 +\n stain.center[2] * 7 +\n stain.front.reduce((s, v, i) => s + v * (i + 1), 0) * 11 +\n stain.wetness * 13 +\n stain.wetRadius * 17 +\n (stain.soaked / (stain.soaked + stain.liters + 1e-6)) * 19\n if (sig === this.signature && this.group.visible) return\n this.signature = sig\n\n const n: Vec3 = stain.normal ?? [0, 1, 0]\n const t1: Vec3 = stain.tangent ?? [1, 0, 0]\n const t2: Vec3 = [n[1] * t1[2] - n[2] * t1[1], n[2] * t1[0] - n[0] * t1[2], n[0] * t1[1] - n[1] * t1[0]]\n smoothOutline(stain.front, profile.stainSubdiv, this.radii)\n const ring = this.ring\n const lift = 0.0015 + 0.0004 * (this.slot % 6)\n const mean = stain.front.reduce((s, v) => s + v, 0) / stain.front.length\n const wet = clamp(stain.wetness, 0, 1)\n const soakRatio = stain.soaked / (stain.soaked + stain.liters + 1e-6)\n\n // Outer film: tinted by the liquid, darker while wet and where it soaked in, fainter once only the mark is left.\n this.tint.setHex(stainColorOf(def))\n const dark = 1 - 0.3 * wet - 0.2 * soakRatio\n const markAlpha = def.leavesMark ? 0.34 : 0.1\n const aMid = (markAlpha + (0.62 - markAlpha) * wet) * (0.75 + 0.25 * Math.min(1, stain.liters * 20 + soakRatio))\n this.writeFan(this.outer, stain.center, n, t1, t2, lift, 1, this.tint.r * dark, this.tint.g * dark, this.tint.b * dark, aMid, aMid * 0.45)\n this.outer.mesh.visible = true\n\n // Inner glossy wet fan, centred where the liquid came in, shrinking as it dries.\n const wr = clamp(stain.wetRadius, 0, 1)\n const showInner = wr > 0.05 && wet > 0.03\n this.inner.mesh.visible = showInner\n if (showInner) {\n this.tint.setHex(def.color)\n const shift = stain.flow ? -mean * 0.1 * (1 - wr) : 0\n const centre: Vec3 = stain.flow\n ? [stain.center[0] + stain.flow[0] * shift, stain.center[1] + stain.flow[1] * shift, stain.center[2] + stain.flow[2] * shift]\n : stain.center\n const a = clamp(def.opacity, 0.2, 0.85) * wet * 0.8\n this.writeFan(this.inner, centre, n, t1, t2, lift + 0.0007, 0.9 * wr, this.tint.r, this.tint.g, this.tint.b, a, a * 0.5)\n }\n this.triangles = ring * (showInner ? 2 : 1)\n this.group.visible = true\n }\n\n private writeFan(\n fan: Fan,\n center: Vec3,\n n: Vec3,\n t1: Vec3,\n t2: Vec3,\n lift: number,\n scale: number,\n r: number,\n g: number,\n b: number,\n aCentre: number,\n aRim: number,\n ): void {\n const ring = this.ring\n const px = center[0] + n[0] * lift\n const py = center[1] + n[1] * lift\n const pz = center[2] + n[2] * lift\n fan.position[0] = px\n fan.position[1] = py\n fan.position[2] = pz\n fan.color[0] = r * 0.85\n fan.color[1] = g * 0.85\n fan.color[2] = b * 0.85\n fan.color[3] = aCentre\n const normalAttr = fan.mesh.geometry.getAttribute('normal') as THREE_NS.BufferAttribute\n for (let i = 0; i <= ring; i++) {\n normalAttr.setXYZ(i, n[0], n[1], n[2])\n }\n normalAttr.needsUpdate = true\n for (let i = 0; i < ring; i++) {\n const a = (i / ring) * Math.PI * 2\n const c = Math.cos(a) * this.radii[i] * scale\n const s = Math.sin(a) * this.radii[i] * scale\n const o = (1 + i) * 3\n fan.position[o] = px + t1[0] * c + t2[0] * s\n fan.position[o + 1] = py + t1[1] * c + t2[1] * s\n fan.position[o + 2] = pz + t1[2] * c + t2[2] * s\n const k = (1 + i) * 4\n fan.color[k] = r\n fan.color[k + 1] = g\n fan.color[k + 2] = b\n fan.color[k + 3] = aRim\n }\n const geometry = fan.mesh.geometry\n ;(geometry.getAttribute('position') as THREE_NS.BufferAttribute).needsUpdate = true\n ;(geometry.getAttribute('color') as THREE_NS.BufferAttribute).needsUpdate = true\n }\n\n dispose(): void {\n for (const fan of [this.outer, this.inner]) fan.mesh.geometry.dispose()\n }\n}\n","import type * as THREE_NS from 'three'\nimport { sampleStream } from '@adatechnology/game-fluids'\nimport type { StreamState } from '@adatechnology/game-fluids'\nimport type { QualityProfile } from './quality'\nimport { clamp } from './util'\nimport type { ThreeLib } from './types'\n\n/** Seconds a stream takes to break up into drops after the world ended it. */\nconst GHOST_TIME = 0.4\n\n/**\n * One stream: a thread along the ballistic path (a tube updated in place) with a growing drop at its leading tip, a trailing drop while it ends,\n * and for thin streams only a sequence of falling drops. The jet narrows as it accelerates.\n */\nexport class StreamVisual {\n readonly tube: THREE_NS.Mesh\n readonly drops: THREE_NS.InstancedMesh\n private readonly positions: Float32Array\n private readonly normals: Float32Array\n private readonly samples: number\n private readonly sides: number\n private readonly matrix: THREE_NS.Matrix4\n private readonly maxDrops: number\n id = ''\n age = 0\n ghostAge = -1\n /** Last known state, kept while the stream breaks into drops. */\n state: StreamState | null = null\n triangles = 0\n\n constructor(\n private readonly THREE: ThreeLib,\n profile: QualityProfile,\n dropGeometry: THREE_NS.SphereGeometry,\n ) {\n const T = THREE\n this.samples = profile.streamSamples\n this.sides = profile.streamSides\n this.maxDrops = Math.max(profile.thinDrops, 2) + 2\n this.positions = new Float32Array(this.samples * this.sides * 3)\n this.normals = new Float32Array(this.samples * this.sides * 3)\n const geometry = new T.BufferGeometry()\n const p = new T.BufferAttribute(this.positions, 3)\n const n = new T.BufferAttribute(this.normals, 3)\n p.setUsage(T.DynamicDrawUsage)\n n.setUsage(T.DynamicDrawUsage)\n geometry.setAttribute('position', p)\n geometry.setAttribute('normal', n)\n const index: number[] = []\n for (let i = 0; i < this.samples - 1; i++) {\n for (let j = 0; j < this.sides; j++) {\n const a = i * this.sides + j\n const b = i * this.sides + ((j + 1) % this.sides)\n const c = (i + 1) * this.sides + j\n const d = (i + 1) * this.sides + ((j + 1) % this.sides)\n index.push(a, c, b, b, c, d)\n }\n }\n geometry.setIndex(index)\n this.tube = new T.Mesh(geometry)\n this.tube.name = 'fluid_stream'\n this.tube.frustumCulled = false\n this.tube.renderOrder = 2\n this.drops = new T.InstancedMesh(dropGeometry, undefined as unknown as THREE_NS.Material, this.maxDrops)\n this.drops.name = 'fluid_stream_drops'\n this.drops.frustumCulled = false\n this.drops.renderOrder = 2\n this.drops.instanceMatrix.setUsage(T.DynamicDrawUsage)\n this.drops.count = 0\n this.matrix = new T.Matrix4()\n }\n\n setMaterial(material: THREE_NS.Material): void {\n this.tube.material = material\n this.drops.material = material\n }\n\n hide(): void {\n this.tube.visible = false\n this.drops.visible = false\n this.drops.count = 0\n this.triangles = 0\n }\n\n private dropAt(slot: number, x: number, y: number, z: number, radius: number): void {\n this.matrix.makeScale(radius, radius, radius).setPosition(x, y, z)\n this.drops.setMatrixAt(slot, this.matrix)\n }\n\n /**\n * Draw the stream. `state` is the world's stream while it lives, or the last known one while ghost (`ghostAge >= 0`).\n */\n update(state: StreamState, gravity: number, dt: number, profile: QualityProfile, time: number): void {\n this.state = state\n this.age += dt\n if (this.ghostAge >= 0) this.ghostAge += dt\n\n const flight = Math.max(0.02, state.flightTime ?? 1)\n const [vx, vy, vz] = state.velocity\n const speed0 = Math.max(0.3, Math.hypot(vx, vy, vz))\n const q = Math.max(state.rate, 0) / 1000\n const r0 = clamp(Math.sqrt(q / (Math.PI * speed0)), 0.0015, 0.03)\n\n const tB = Math.min(flight, this.age)\n // The tail leaves the origin at free fall once the world stopped the stream.\n const tA = this.ghostAge >= 0 ? Math.min(flight, this.ghostAge) : 0\n\n let drops = 0\n const thin = state.thin && this.ghostAge < 0\n\n if (thin) {\n this.tube.visible = false\n this.triangles = 0\n const n = profile.thinDrops\n const phase = time * 1.3\n for (let k = 0; k < n && drops < this.maxDrops; k++) {\n const tau = ((phase + k / n) % 1) * flight\n if (tau > tB) continue\n const p = sampleStream(state, gravity, tau)\n const grow = Math.min(1, tau / (0.12 * flight + 0.02))\n this.dropAt(drops++, p[0], p[1], p[2], Math.max(0.002, r0 * 1.8) * (0.4 + 0.6 * grow))\n }\n } else if (tB - tA > 0.015) {\n this.writeTube(state, gravity, tA, tB, r0, speed0)\n this.tube.visible = true\n this.triangles = (this.samples - 1) * this.sides * 2\n // Leading drop that grows and detaches while the jet is still advancing; trailing drop while it ends.\n if (tB < flight) {\n const p = sampleStream(state, gravity, tB)\n const w = this.radiusAt(state, gravity, tB, r0, speed0)\n this.dropAt(drops++, p[0], p[1], p[2], w * 1.35)\n }\n if (this.ghostAge >= 0) {\n const p = sampleStream(state, gravity, tA)\n const w = this.radiusAt(state, gravity, tA, r0, speed0)\n this.dropAt(drops++, p[0], p[1], p[2], w * 1.4 * (1 - this.ghostAge / GHOST_TIME * 0.4))\n }\n } else {\n this.tube.visible = false\n this.triangles = 0\n if (tA < flight) {\n // Only the drop is left.\n const p = sampleStream(state, gravity, this.ghostAge >= 0 ? tA : tB)\n this.dropAt(drops++, p[0], p[1], p[2], Math.max(0.003, r0 * 1.3))\n }\n }\n\n this.drops.count = drops\n this.drops.visible = drops > 0\n this.drops.instanceMatrix.needsUpdate = true\n this.triangles += drops * 24\n }\n\n /** The ghost is over once its tail reached the landing. */\n get finished(): boolean {\n return this.ghostAge >= 0 && (this.ghostAge >= GHOST_TIME || this.ghostAge >= (this.state?.flightTime ?? 0))\n }\n\n private radiusAt(state: StreamState, gravity: number, t: number, r0: number, speed0: number): number {\n const vy = state.velocity[1] - gravity * t\n const speed = Math.max(0.3, Math.hypot(state.velocity[0], vy, state.velocity[2]))\n const fade = this.ghostAge >= 0 ? clamp(1 - this.ghostAge / GHOST_TIME, 0.15, 1) : 1\n return r0 * Math.sqrt(speed0 / speed) * fade\n }\n\n private writeTube(state: StreamState, gravity: number, tA: number, tB: number, r0: number, speed0: number): void {\n const n = this.samples\n const sides = this.sides\n for (let i = 0; i < n; i++) {\n const k = i / (n - 1)\n const t = tA + (tB - tA) * k\n const p = sampleStream(state, gravity, t)\n const vx = state.velocity[0]\n const vy = state.velocity[1] - gravity * t\n const vz = state.velocity[2]\n const l = Math.hypot(vx, vy, vz) || 1\n const tx = vx / l\n const ty = vy / l\n const tz = vz / l\n // Any vector not parallel to the tangent gives the first side axis.\n const ax = Math.abs(tz) < 0.9 ? 0 : 1\n const az = Math.abs(tz) < 0.9 ? 1 : 0\n let b1x = ty * az - tz * 0\n let b1y = tz * ax - tx * az\n let b1z = tx * 0 - ty * ax\n const bl = Math.hypot(b1x, b1y, b1z) || 1\n b1x /= bl\n b1y /= bl\n b1z /= bl\n const b2x = ty * b1z - tz * b1y\n const b2y = tz * b1x - tx * b1z\n const b2z = tx * b1y - ty * b1x\n // Rounded ends: the radius tapers to a bead at both ends.\n const end = Math.min(1, 0.35 + Math.min(k, 1 - k) * 8)\n const r = this.radiusAt(state, gravity, t, r0, speed0) * end\n for (let j = 0; j < sides; j++) {\n const a = (j / sides) * Math.PI * 2\n const c = Math.cos(a)\n const s = Math.sin(a)\n const nx = b1x * c + b2x * s\n const ny = b1y * c + b2y * s\n const nz = b1z * c + b2z * s\n const o = (i * sides + j) * 3\n this.positions[o] = p[0] + nx * r\n this.positions[o + 1] = p[1] + ny * r\n this.positions[o + 2] = p[2] + nz * r\n this.normals[o] = nx\n this.normals[o + 1] = ny\n this.normals[o + 2] = nz\n }\n }\n const g = this.tube.geometry\n ;(g.getAttribute('position') as THREE_NS.BufferAttribute).needsUpdate = true\n ;(g.getAttribute('normal') as THREE_NS.BufferAttribute).needsUpdate = true\n }\n\n start(id: string): void {\n this.id = id\n this.age = 0\n this.ghostAge = -1\n this.state = null\n }\n\n dispose(): void {\n this.tube.geometry.dispose()\n this.drops.dispose()\n }\n}\n","import type * as THREE_NS from 'three'\nimport type { FluidEvent, StainState, StreamState } from '@adatechnology/game-fluids'\nimport { LiquidBody } from './liquid-body'\nimport { MaterialCache } from './materials'\nimport { ParticlePool } from './particles'\nimport { profileOf } from './quality'\nimport { StainVisual } from './stains'\nimport { StreamVisual } from './streams'\nimport type { BindOptions, FluidQuality, FluidRenderer, FluidRendererOptions, FluidRendererStats, ThreeLib } from './types'\n\n/**\n * Draws a `FluidWorld` with three.js. It only reads the world state (plus `splash` events for droplets), so a LAN client that receives the\n * same world state draws the same liquids.\n */\nexport function createFluidRenderer(THREE: ThreeLib, options: FluidRendererOptions): FluidRenderer {\n const { scene, fluids } = options\n const quality: FluidQuality = options.quality ?? 'medium'\n const profile = profileOf(quality)\n const materials = new MaterialCache(THREE, options.envMap ?? null)\n const root = new THREE.Group()\n root.name = 'fluid_renderer'\n scene.add(root)\n const particles = new ParticlePool(THREE, profile.maxParticles, options.pointScale ?? 600)\n root.add(particles.points)\n const dropGeometry = new THREE.SphereGeometry(1, 8, 6)\n\n const bodies = new Map<string, LiquidBody>()\n const streamsActive = new Map<string, StreamVisual>()\n const streamsFree: StreamVisual[] = []\n let streamsCreated = 0\n const stainsActive = new Map<string, StainVisual>()\n const stainsFree: StainVisual[] = []\n let stainsCreated = 0\n let time = 0\n let disposed = false\n\n const offSplash = fluids.on('splash', (e: FluidEvent) => {\n if (e.type !== 'splash' || disposed) return\n const def = fluids.liquids.get(e.liquid)\n if (!def) return\n particles.splash(e.point, e.intensity, def.color, def.opacity, profile.splashDroplets)\n })\n\n // ---- streams ----\n\n const acquireStream = (id: string): StreamVisual | null => {\n let v = streamsFree.pop() ?? null\n if (!v) {\n if (streamsCreated >= profile.maxStreams) return null\n streamsCreated++\n v = new StreamVisual(THREE, profile, dropGeometry)\n root.add(v.tube, v.drops)\n }\n v.start(id)\n return v\n }\n\n const releaseStream = (v: StreamVisual): void => {\n v.hide()\n streamsActive.delete(v.id)\n streamsFree.push(v)\n }\n\n const syncStreams = (dt: number): void => {\n const live = fluids.streams()\n const seen = new Set<string>()\n // Biggest first, so the budget keeps the visible ones.\n live.sort((a: StreamState, b: StreamState) => b.rate - a.rate)\n for (const s of live) {\n seen.add(s.id)\n let v = streamsActive.get(s.id)\n if (!v) {\n const fresh = acquireStream(s.id)\n if (!fresh) continue\n v = fresh\n streamsActive.set(s.id, v)\n }\n const def = fluids.liquids.get(s.liquid)\n if (!def) continue\n v.ghostAge = -1\n v.setMaterial(materials.liquidStream(def))\n v.update(s, fluids.gravity, dt, profile, time)\n }\n for (const v of [...streamsActive.values()]) {\n if (seen.has(v.id)) continue\n // The world ended it: let it break into drops.\n if (v.ghostAge < 0) v.ghostAge = 0\n if (!v.state || v.finished) {\n releaseStream(v)\n continue\n }\n v.update(v.state, fluids.gravity, dt, profile, time)\n if (v.finished) releaseStream(v)\n }\n }\n\n // ---- stains ----\n\n const syncStains = (): void => {\n const all = fluids.stains()\n // Keep the newest stains when the budget is smaller than the world.\n const wanted = all.length > profile.maxStains ? [...all].sort((a: StainState, b: StainState) => (a.age ?? 0) - (b.age ?? 0)).slice(0, profile.maxStains) : all\n const ids = new Set(wanted.map((s: StainState) => s.id))\n for (const [id, v] of [...stainsActive]) {\n if (ids.has(id)) continue\n v.hide()\n stainsActive.delete(id)\n stainsFree.push(v)\n }\n for (const s of wanted) {\n const def = fluids.liquids.get(s.liquid)\n if (!def) continue\n let v = stainsActive.get(s.id)\n if (!v) {\n v = stainsFree.pop()\n if (!v) {\n if (stainsCreated >= profile.maxStains) continue\n v = new StainVisual(THREE, profile, stainsCreated++)\n root.add(v.group)\n }\n v.stainId = s.id\n v.signature = Number.NaN\n v.assign(def, materials)\n stainsActive.set(s.id, v)\n }\n v.update(s, def, profile)\n }\n }\n\n // ---- public ----\n\n const renderer: FluidRenderer = {\n bindContainer(containerId: string, object: THREE_NS.Object3D, opts: BindOptions = {}) {\n renderer.unbindContainer(containerId)\n bodies.set(containerId, new LiquidBody(THREE, containerId, object, opts.innerOffset ?? [0, 0, 0]))\n },\n\n unbindContainer(containerId: string) {\n const body = bodies.get(containerId)\n if (!body) return\n body.dispose()\n bodies.delete(containerId)\n },\n\n update(dt: number) {\n if (disposed) return\n time += dt\n for (const body of bodies.values()) body.update(dt, fluids, materials, profile, particles)\n syncStreams(dt)\n syncStains()\n particles.update(dt, fluids.gravity)\n },\n\n clear() {\n for (const v of [...streamsActive.values()]) releaseStream(v)\n for (const [id, v] of [...stainsActive]) {\n v.hide()\n stainsActive.delete(id)\n stainsFree.push(v)\n }\n particles.clear()\n },\n\n dispose() {\n if (disposed) return\n disposed = true\n offSplash()\n for (const body of bodies.values()) body.dispose()\n bodies.clear()\n for (const v of [...streamsActive.values(), ...streamsFree]) v.dispose()\n for (const v of [...stainsActive.values(), ...stainsFree]) v.dispose()\n streamsActive.clear()\n stainsActive.clear()\n streamsFree.length = 0\n stainsFree.length = 0\n particles.dispose()\n dropGeometry.dispose()\n materials.dispose()\n scene.remove(root)\n root.clear()\n },\n\n stats(): FluidRendererStats {\n let triangles = 0\n let containers = 0\n for (const body of bodies.values()) {\n triangles += body.triangles\n if (body.visible) containers++\n }\n for (const v of streamsActive.values()) triangles += v.triangles\n for (const v of stainsActive.values()) triangles += v.triangles\n return {\n quality,\n containers,\n streams: streamsActive.size,\n stains: stainsActive.size,\n particles: particles.count,\n triangles,\n budget: { stains: profile.maxStains, streams: profile.maxStreams, particles: profile.maxParticles },\n }\n },\n }\n\n return renderer\n}\n\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adatechnology/game-fluids-three",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "three.js renderer for @adatechnology/game-fluids: liquid surfaces inside containers, streams with a drop at the tip, puddles that grow from a flow front, wet surfaces that reflect and dry from the edge.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"game",
|
|
8
|
+
"fluids",
|
|
9
|
+
"liquids",
|
|
10
|
+
"three",
|
|
11
|
+
"threejs",
|
|
12
|
+
"puddles",
|
|
13
|
+
"wet"
|
|
14
|
+
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/Andersonfrfilho/adatechnology-game-kit.git",
|
|
18
|
+
"directory": "packages/game-fluids-three"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "dist/index.js",
|
|
25
|
+
"module": "dist/index.js",
|
|
26
|
+
"types": "dist/index.d.ts",
|
|
27
|
+
"unpkg": "dist/index.global.js",
|
|
28
|
+
"jsdelivr": "dist/index.global.js",
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./global": "./dist/index.global.js"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@adatechnology/game-fluids": "0.1.1"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"three": "^0.160.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^22.10.7",
|
|
48
|
+
"@types/three": "^0.160.0",
|
|
49
|
+
"three": "^0.160.1",
|
|
50
|
+
"tsup": "^8.5.1",
|
|
51
|
+
"typescript": "^5.7.3",
|
|
52
|
+
"vitest": "^3.2.4"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "tsup",
|
|
56
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
57
|
+
"test": "vitest run"
|
|
58
|
+
}
|
|
6
59
|
}
|