Add a few more mesh types

This commit is contained in:
2026-04-14 08:38:50 -05:00
parent 378227c377
commit 0b570b5fd6
23 changed files with 875 additions and 83 deletions
+17 -17
View File
@@ -4,7 +4,7 @@
// Returns the smallest power of two >= n.
function nextPow2(n) {
if (n <= 0) return 1;
if(n <= 0) return 1;
let p = 1;
while (p < n) p <<= 1;
return p;
@@ -57,10 +57,10 @@ function computeOutputSize() {
let outW = state.width;
let outH = state.height;
// Apply minimum-size constraints first so pow2 rounding accounts for them.
if (state.minWidth4 && outW < 4) outW = 4;
if (state.minHeight4 && outH < 4) outH = 4;
if (state.padWidthPow2) outW = nextPow2(outW);
if (state.padHeightPow2) outH = nextPow2(outH);
if(state.minWidth4 && outW < 4) outW = 4;
if(state.minHeight4 && outH < 4) outH = 4;
if(state.padWidthPow2) outW = nextPow2(outW);
if(state.padHeightPow2) outH = nextPow2(outH);
return { outW, outH };
}
@@ -69,8 +69,8 @@ function buildPaddedPixels() {
const src = state.pixels;
// Zero-filled Uint8ClampedArray = fully transparent black padding.
const out = new Uint8ClampedArray(outW * outH * 4);
for (let y = 0; y < state.height; y++) {
for (let x = 0; x < state.width; x++) {
for(let y = 0; y < state.height; y++) {
for(let x = 0; x < state.width; x++) {
const si = (y * state.width + x) * 4;
const di = (y * outW + x) * 4;
out[di] = src[si];
@@ -87,8 +87,8 @@ function buildPaddedPixels() {
const CHECKER_CELL = 8;
function drawCheckerboard(w, h) {
for (let y = 0; y < h; y += CHECKER_CELL) {
for (let x = 0; x < w; x += CHECKER_CELL) {
for(let y = 0; y < h; y += CHECKER_CELL) {
for(let x = 0; x < w; x += CHECKER_CELL) {
ctx.fillStyle = ((x / CHECKER_CELL + y / CHECKER_CELL) % 2 === 0) ? "#c8c8c8" : "#ffffff";
ctx.fillRect(x, y, Math.min(CHECKER_CELL, w - x), Math.min(CHECKER_CELL, h - y));
}
@@ -96,7 +96,7 @@ function drawCheckerboard(w, h) {
}
function render() {
if (!state.pixels) return;
if(!state.pixels) return;
const { pixels, width, height } = buildPaddedPixels();
const cw = width * state.scale;
@@ -105,7 +105,7 @@ function render() {
canvas.width = cw;
canvas.height = ch;
if (state.bg === "grid") {
if(state.bg === "grid") {
drawCheckerboard(cw, ch);
} else {
ctx.fillStyle = state.bg;
@@ -122,7 +122,7 @@ function render() {
// ─── Info update ─────────────────────────────────────────────────────────────
function updateInfo() {
if (!state.pixels) return;
if(!state.pixels) return;
const { outW, outH } = computeOutputSize();
const bytes = DTF.HEADER_SIZE + outW * outH * DTF.BPP[state.format];
infoInputSize.textContent = `${state.width} × ${state.height}`;
@@ -189,8 +189,8 @@ function applyImageData(width, height, data, filename) {
}
function handleFile(file) {
if (!file) return;
if (file.name.toLowerCase().endsWith(".dtf")) {
if(!file) return;
if(file.name.toLowerCase().endsWith(".dtf")) {
loadDTF(file);
} else {
loadStandardImage(file);
@@ -200,7 +200,7 @@ function handleFile(file) {
// ─── Export ───────────────────────────────────────────────────────────────────
function exportDTF() {
if (!state.pixels) return;
if(!state.pixels) return;
const { pixels, width, height } = buildPaddedPixels();
const buf = DTF.encode(width, height, pixels, state.format);
const blob = new Blob([buf], { type: "application/octet-stream" });
@@ -214,7 +214,7 @@ function exportDTF() {
}
function exportPNG() {
if (!state.pixels) return;
if(!state.pixels) return;
const { pixels, width, height } = buildPaddedPixels();
DuskPNG.download(`${state.filename}.png`, width, height, pixels);
}
@@ -232,7 +232,7 @@ scaleInput.addEventListener("input", () => {
bgSwatches.addEventListener("click", e => {
const btn = e.target.closest(".bg-swatch");
if (!btn) return;
if(!btn) return;
bgSwatches.querySelectorAll(".bg-swatch").forEach(b => b.classList.remove("active"));
btn.classList.add("active");
state.bg = btn.dataset.bg;