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