UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

96 lines (67 loc) 2.94 kB
import { v3_grid_apply_diffusion } from "./solver/v3_grid_apply_diffusion.js"; import { v3_grid_apply_advection_forward } from "./solver/v3_grid_apply_advection_forward.js"; export class FluidSimulator { /** * * @type {ArrayBuffer|null} */ buffer = null; ensure_buffer(size) { if (this.buffer === null || this.buffer.byteLength < size) { this.buffer = new ArrayBuffer(size); } } /** * * @param {FluidField} field * @param {number} time_delta_in_seconds */ step(field, time_delta_in_seconds) { // create buffer big enough to store all attribute twice const resolution = field.resolution; const attribute_cell_count = resolution[0] * resolution[1] * resolution[2]; const attribute_byte_size = attribute_cell_count * 4; const field_byte_size = field.getAttributeCount() * attribute_byte_size; this.ensure_buffer(field_byte_size * 2); const sim_buffer = this.buffer; // remember current data new Uint8Array(sim_buffer, 0, field_byte_size).set(new Uint8Array(field.buffer, 0, field_byte_size)) let ping_pong_index = 0; const DIFFUSE_STEPS = 2; for (let i = 0; i < 3; i++) { // perform diffusion let source = new Float32Array(sim_buffer, attribute_byte_size * i, attribute_cell_count) let target = new Float32Array(sim_buffer, field_byte_size + attribute_byte_size * i, attribute_cell_count); const ping_pong = [source, target]; ping_pong_index = 0; for (let j = 0; j < DIFFUSE_STEPS; j++) { source = ping_pong[ping_pong_index % 2]; target = ping_pong[(ping_pong_index + 1) % 2]; v3_grid_apply_diffusion(target, source, resolution); ping_pong_index++; } } ping_pong_index = DIFFUSE_STEPS; const inputs = []; const outputs = []; for (let i = 0; i < 3; i++) { const source = ping_pong_index % 2 const target = (ping_pong_index + 1) % 2 inputs[i] = new Float32Array( sim_buffer, source * field_byte_size + attribute_byte_size * i, attribute_cell_count ); outputs[i] = new Float32Array( sim_buffer, target * field_byte_size + attribute_byte_size * i, attribute_cell_count ); } ping_pong_index++; // advection v3_grid_apply_advection_forward(outputs, inputs, resolution, time_delta_in_seconds); if (ping_pong_index % 2 !== 0) { // data is not at source field.attachBuffer(sim_buffer, field_byte_size); } else { field.attachBuffer(sim_buffer, 0); } } }