75 lines
2.5 KiB
JavaScript
75 lines
2.5 KiB
JavaScript
|
"use strict";
|
||
|
import { writeFile } from "fs/promises";
|
||
|
import { Canvas, loadImage } from 'canvas';
|
||
|
|
||
|
const TILE_WIDTH = 256; // pixels
|
||
|
const WIDTH = 8; // tiles
|
||
|
const FACE_WIDTH = TILE_WIDTH * WIDTH; // pixels
|
||
|
|
||
|
async function main() {
|
||
|
const canvas = new Canvas(FACE_WIDTH, FACE_WIDTH);
|
||
|
const context = canvas.getContext('2d');
|
||
|
|
||
|
for (let face = 1; face <= 6; face++) {
|
||
|
const face4 = toBase(face, 4).padStart(2, "0");
|
||
|
for (let position = 0; position < 64; position++) {
|
||
|
const position4 = toBase(position, 4).padStart(3, "0");
|
||
|
const image = await loadImage(`out/${face4}${position4}.jpg`);
|
||
|
const [x, y] = quadtreePositionToXY(position4);
|
||
|
context.drawImage(image, x * TILE_WIDTH, y * TILE_WIDTH, TILE_WIDTH, TILE_WIDTH);
|
||
|
}
|
||
|
const output = canvas.toBuffer('image/png');
|
||
|
await writeFile(`stitched/${face}.png`, output);
|
||
|
console.log(`Stitched face #${face}.`);
|
||
|
}
|
||
|
console.log("Done stitching! Resultant files in stitched directory.");
|
||
|
|
||
|
console.log("Stitching faces into cubemap");
|
||
|
|
||
|
const canvas2 = new Canvas(FACE_WIDTH * 4, FACE_WIDTH * 3);
|
||
|
const context2 = canvas2.getContext("2d");
|
||
|
const positionIndex = [[1, 1], [2, 1], [3, 1], [0, 1], [1, 0], [1, 2]];
|
||
|
for (let i = 1; i <= 6; i++) {
|
||
|
const [x, y] = positionIndex[i - 1];
|
||
|
const image = await loadImage(`stitched/${i}.png`);
|
||
|
context2.drawImage(image, FACE_WIDTH * x, FACE_WIDTH * y, FACE_WIDTH, FACE_WIDTH);
|
||
|
}
|
||
|
|
||
|
const output = canvas2.toBuffer('image/png');
|
||
|
await writeFile(`stitched.png`, output);
|
||
|
}
|
||
|
main();
|
||
|
|
||
|
|
||
|
function quadtreePositionToXY(position) {
|
||
|
let x = 0;
|
||
|
let y = 0;
|
||
|
// Loop through each position value and treat it as an instruction.
|
||
|
for (let j = 0; j < position.length; j++) {
|
||
|
// The delta value is equal to the width of each tile at the current instruction depth.
|
||
|
let delta = WIDTH / (2 ** (j + 1));
|
||
|
switch (position[j]) {
|
||
|
case "0":
|
||
|
// Do nothing
|
||
|
break;
|
||
|
case "1":
|
||
|
// Move right
|
||
|
x = x + delta;
|
||
|
break;
|
||
|
case "2":
|
||
|
// Move down
|
||
|
y = y + delta;
|
||
|
break;
|
||
|
case "3":
|
||
|
// Move down and right
|
||
|
y = y + delta;
|
||
|
x = x + delta;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return [x, y];
|
||
|
}
|
||
|
|
||
|
function toBase(number, base) {
|
||
|
return number.toString(base);
|
||
|
}
|