UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

123 lines (86 loc) 2.83 kB
class FluidAttribute { name = "unnamed" /** * * @type {Float32Array} */ data = null } /** * Represents a space where fluid simulation happens * * @see 2019 GDC talk by Runard Rupert "Wind Simulation in God of War" https://www.youtube.com/watch?v=dDgyBKkSf7A * @see Inspired by GDC talk "Interactive Wind and Vegetation in 'God of War'" - https://www.youtube.com/watch?v=MKX45_riWQA */ export class FluidField { #attributes = []; #size = [0, 0, 0] #resolution = [0, 0, 0] buffer = null; addAttribute(name) { const attribute = new FluidAttribute(); attribute.name = name; const index = this.#attributes.length; this.#attributes.push(attribute); return index; } #findAttribute(name) { return this.#attributes.find(a => a.name === name); } /** * * @param {string} name * @return {Float32Array} */ getAttributeData(name) { return this.#findAttribute(name)?.data; } getAttributeCount() { return this.#attributes.length; } /** * * @param {ArrayBuffer} buffer * @param {number} offset */ attachBuffer(buffer, offset = 0) { const attribute_count = this.#attributes.length; const cell_count = this.#resolution[0] * this.#resolution[1] * this.#resolution[2]; for (let i = 0; i < attribute_count; i++) { const attribute = this.#attributes[i]; const array = new Float32Array(buffer, offset + i * cell_count * 4, cell_count); attribute.data = array; } this.buffer = buffer; } setAttributeAt(attribute_index, x, y, z, value) { const attribute = this.#attributes[attribute_index]; const data = attribute.data; data[z * this.#resolution[0] * this.#resolution[1] + y * this.#resolution[0] + x] = value; } build() { const attribute_count = this.#attributes.length; const cell_count = this.#resolution[0] * this.#resolution[1] * this.#resolution[2]; const data_buffer = new ArrayBuffer(cell_count * attribute_count * 4); this.attachBuffer(data_buffer); } set size(v) { const width = v[0]; const height = v[1]; const depth = v[2]; this.#size[0] = width; this.#size[1] = height; this.#size[2] = depth } set resolution(v) { const width = v[0]; const height = v[1]; const depth = v[2]; this.#resolution[0] = width; this.#resolution[1] = height; this.#resolution[2] = depth } get resolution() { return this.#resolution; } }