@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
90 lines (65 loc) • 2.44 kB
JavaScript
import { assert } from "../../../core/assert.js";
/**
* Was originally written for TAA jitter sequence optimization in order to reduce maximum impulse
* @template T
* @param {T[]} sequence
* @param {number} dimensions
* @param {number} offset
* @param {number} count
* @param {function(address0:number, address1:number, sequence:T[]):number} cost_function
* @param {*} [cost_function_ctx]
*/
export function optimize_cyclic_sequence_pairwise(
sequence,
dimensions,
offset,
count,
cost_function,
cost_function_ctx
) {
assert.isNonNegativeInteger(dimensions, 'dimensions');
assert.isNonNegativeInteger(offset, 'offset');
assert.isNonNegativeInteger(count, 'count');
assert.isFunction(cost_function, 'cost_function');
let swaps = 0;
let distance_max = (count - 1) >>> 1;
function index_to_address(index) {
const wrapped_index = (index + count) % count;
return offset + wrapped_index * dimensions;
}
function move(from, to){
const i0 = index_to_address(from);
const i1 = index_to_address(to);
const clip = sequence.splice(i0, dimensions);
sequence.splice(i1, 0, ...clip);
}
function pair_cost(i0, i1){
return cost_function.call(cost_function_ctx, index_to_address(i0), index_to_address(i1), sequence)
}
main: do {
swaps = 0;
for (let from = 0; from < count; from++) {
for (let distance = -distance_max; distance <= distance_max; distance++) {
if (distance === 0) {
continue;
}
// estimate swap benefit
const to = from+distance;
const removal_gain = pair_cost(from-1, from+1) - (
pair_cost(from-1, from) + pair_cost(from, from+1)
);
move(from, to);
const insertion_gain = ( pair_cost(to-1, to) + pair_cost(to, to+1))
- pair_cost(to -1, to+1);
const move_cost =insertion_gain + removal_gain;
if (move_cost >= 0) {
// bad swap, undo
move(to, from);
continue;
}
swaps++;
continue main;
}
}
} while (swaps > 0);
}