@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
123 lines (86 loc) • 2.83 kB
JavaScript
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;
}
}