@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
101 lines (74 loc) • 3.22 kB
JavaScript
import { assert } from "../../../../core/assert.js";
import { passThrough } from "../../../../core/function/passThrough.js";
import { clamp01 } from "../../../../core/math/clamp01.js";
import { NumericInterval } from "../../../../core/math/interval/NumericInterval.js";
import { ParameterLookupTable } from "../../../graphics/particles/particular/engine/parameter/ParameterLookupTable.js";
import { sampler2d_scale } from "../../../graphics/texture/sampler/resize/sampler2d_scale.js";
import { Sampler2D } from "../../../graphics/texture/sampler/Sampler2D.js";
import { logger } from "../../../logging/GlobalLogger.js";
const heatmap_lut = new ParameterLookupTable(4);
heatmap_lut.write([
0, 0, 0, 255,
0, 0, 255, 255,
0, 179, 179, 255,
0, 255, 0, 255,
255, 255, 0, 255,
255, 5, 5, 255
]);
heatmap_lut.computeUniformPositions();
/**
* Color to use when sampled value is NaN
* @type {number[]}
*/
const NAN_COLOR = [0, 0, 0, 0];
/**
* @param {Object} params
* @param {TerrainOverlay} params.overlay
* @param {Sampler2D} params.sampler
* @param {ParameterLookupTable} [params.lut]
* @param {NumericInterval} [params.range] Range of values of interest within the sampler that are to be mapped onto LUT
* @param {function(number):number} [params.lookupScaleFunction]
* @param {number} [params.channel]
*/
export function paintTerrainOverlayViaLookupTable({
overlay,
sampler,
lut = heatmap_lut,
range = new NumericInterval(0, 1),
lookupScaleFunction = passThrough,
channel = 0
}) {
assert.isNonNegativeInteger(channel, 'channel');
assert.lessThan(channel, sampler.itemSize);
let i, j;
const colorSample = [];
const w = overlay.size.x;
const h = overlay.size.y;
const buffer = Sampler2D.uint8(4, w, h);
// rescale source
const scaled_sampler = sampler.clone();
scaled_sampler.resize(w, h);
sampler2d_scale(sampler, scaled_sampler);
let NaN_count = 0;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
const p = scaled_sampler.readChannel(i, j, channel);
if (Number.isNaN(p)) {
// handle NaN values by writing special color
buffer.write(i, j, NAN_COLOR);
NaN_count++;
continue;
}
const transformed_value = lookupScaleFunction(p);
const remapped_value = range.normalizeValue(transformed_value);
const position = clamp01(remapped_value);
lut.sample(position, colorSample);
buffer.write(i, j, colorSample);
}
}
overlay.clear();
overlay.writeData(buffer.data);
if (NaN_count > 0) {
logger.warn(`sampler had ${NaN_count} NaN values`);
}
}