UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

166 lines (115 loc) 4.44 kB
import { float_to_uint8 } from "../../../core/binary/float_to_uint8.js"; import { max2 } from "../../../core/math/max2.js"; import { CanvasView } from "../../../view/elements/CanvasView.js"; import EmptyView from "../../../view/elements/EmptyView.js"; import { Sampler2D } from "../../graphics/texture/sampler/Sampler2D.js"; export class SliceVisualiser extends EmptyView { #data = null; #views = []; #slices = []; #resolution = [0, 0, 0]; #imageData = null; #channelCount = 1 #drawMethod = (out, out_offset, sample, channelCount) => { let i = 0; for (; i < channelCount; i++) { out[out_offset + i] = float_to_uint8(sample[i]) } if (channelCount < 4) { out[out_offset + 3] = 255; } } /** * */ constructor() { super({ classList: ['slice-visualizer'] }); this.on.linked.add(this.layout, this); this.size.onChanged.add(this.layout, this); } draw() { const resolution_x = this.#resolution[0]; const resolution_y = this.#resolution[1]; const resolution_z = this.#resolution[2]; const imageData = this.#imageData; const slice_size = resolution_x * resolution_y; const data = this.#data; const sample = new Float32Array(this.#channelCount); for (let i = 0; i < resolution_z; i++) { const view = this.#views[i]; for (let j = 0; j < slice_size; j++) { const j4 = j * 4; for (let k = 0; k < this.#channelCount; k++) { const channel = data[slice_size * k + j]; sample[k] = channel; } this.#drawMethod(imageData.data, j4, sample, this.#channelCount); } view.context2d.putImageData(imageData, 0, 0); } } layout() { const resolution_x = this.#resolution[0]; const resolution_y = this.#resolution[1]; const resolution_z = this.#resolution[2]; const width = this.size.x; const grid_width = max2(1, Math.floor(width / resolution_x)); for (let i = 0; i < resolution_z; i++) { const view = this.#views[i]; const grid_x = i % grid_width; const grid_y = Math.floor(i / grid_width); view.position.set(grid_x * resolution_x, grid_y * resolution_y); } } /** * * @param {ArrayBuffer} data * @param {number[]} resolution */ setData( data, resolution) { this.#data = new Float32Array(data); this.#resolution = resolution; const resolution_x = this.#resolution[0]; const resolution_y = this.#resolution[1]; const resolution_z = this.#resolution[2]; const slice_size = resolution_x * resolution_y; /** * * @type {ImageData|null} */ this.#imageData = null; let slice_index = 0; for (; slice_index < resolution_z; slice_index++) { this.#slices[slice_index] = new Sampler2D(new Float32Array(data, slice_index * slice_size * 4, slice_size), 1, resolution_x, resolution_y); let child; if (slice_index + 1 >= this.#views.length) { child = new CanvasView(); this.#views[slice_index] = child this.addChild(child); } else { child = this.#views[slice_index]; } child.size.set(resolution_x, resolution_y); if (this.#imageData === null) { this.#imageData = child.context2d.getImageData(0, 0, resolution_x, resolution_y); } child.css({ position: "absolute", left: 0, top: 0 }); this.#views[slice_index] = child; this.addChild(child); } //remove left-overs for (; slice_index < this.#slices.length; slice_index++) { this.#slices.splice(slice_index, 1); const view = this.#views.splice(slice_index, 1)[0]; this.removeChild(view); slice_index--; } this.layout(); } }