"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateGreedyQuads = generateGreedyQuads;
exports.generateQuadsForVoxelBox = generateQuadsForVoxelBox;
function getVoxel(voxels, dims, x, y, z) {
    if (x < 0 || y < 0 || z < 0)
        return 0;
    if (x >= dims[0] || y >= dims[1] || z >= dims[2])
        return 0;
    const index = x + dims[0] * (y + dims[1] * z);
    return voxels[index] ?? 0;
}
function mergeMask(quads, mask, dimsU, dimsV, axis, plane) {
    let n = 0;
    for (let j = 0; j < dimsV; j += 1) {
        for (let i = 0; i < dimsU;) {
            const cell = mask[n];
            if (!cell) {
                i += 1;
                n += 1;
                continue;
            }
            const material = cell.material;
            const normal = cell.normal;
            let width = 1;
            while (i + width < dimsU) {
                const next = mask[n + width];
                if (!next || next.material !== material || next.normal !== normal) {
                    break;
                }
                width += 1;
            }
            let height = 1;
            outer: while (j + height < dimsV) {
                for (let w = 0; w < width; w += 1) {
                    const next = mask[n + w + height * dimsU];
                    if (!next || next.material !== material || next.normal !== normal) {
                        break outer;
                    }
                }
                height += 1;
            }
            const origin = [0, 0, 0];
            const u = (axis + 1) % 3;
            const v = (axis + 2) % 3;
            origin[u] = i;
            origin[v] = j;
            origin[axis] = plane;
            quads.push({
                material,
                axis,
                normal,
                plane,
                origin,
                size: [width, height],
            });
            for (let h = 0; h < height; h += 1) {
                for (let w = 0; w < width; w += 1) {
                    mask[n + w + h * dimsU] = null;
                }
            }
            i += width;
            n += width;
        }
        n = (j + 1) * dimsU;
    }
}
function generateGreedyQuads(voxels, dimensions) {
    const quads = [];
    for (let axisIndex = 0; axisIndex < 3; axisIndex += 1) {
        const axis = axisIndex;
        const u = (axis + 1) % 3;
        const v = (axis + 2) % 3;
        const dimsU = dimensions[u];
        const dimsV = dimensions[v];
        const dimsAxis = dimensions[axis];
        const mask = new Array(dimsU * dimsV);
        for (let slice = 0; slice <= dimsAxis; slice += 1) {
            // Positive normals (faces on the "back" of the slice)
            for (let j = 0; j < dimsV; j += 1) {
                for (let i = 0; i < dimsU; i += 1) {
                    const aCoords = [0, 0, 0];
                    aCoords[axis] = slice - 1;
                    aCoords[u] = i;
                    aCoords[v] = j;
                    const bCoords = [0, 0, 0];
                    bCoords[axis] = slice;
                    bCoords[u] = i;
                    bCoords[v] = j;
                    const a = slice > 0 ? getVoxel(voxels, dimensions, aCoords[0], aCoords[1], aCoords[2]) : 0;
                    const b = slice < dimsAxis ? getVoxel(voxels, dimensions, bCoords[0], bCoords[1], bCoords[2]) : 0;
                    if (a && (!b || a !== b)) {
                        mask[i + dimsU * j] = { material: a, normal: 1 };
                    }
                    else {
                        mask[i + dimsU * j] = null;
                    }
                }
            }
            mergeMask(quads, mask, dimsU, dimsV, axis, slice);
            // Negative normals (faces on the "front" of the slice)
            for (let j = 0; j < dimsV; j += 1) {
                for (let i = 0; i < dimsU; i += 1) {
                    const aCoords = [0, 0, 0];
                    aCoords[axis] = slice - 1;
                    aCoords[u] = i;
                    aCoords[v] = j;
                    const bCoords = [0, 0, 0];
                    bCoords[axis] = slice;
                    bCoords[u] = i;
                    bCoords[v] = j;
                    const a = slice > 0 ? getVoxel(voxels, dimensions, aCoords[0], aCoords[1], aCoords[2]) : 0;
                    const b = slice < dimsAxis ? getVoxel(voxels, dimensions, bCoords[0], bCoords[1], bCoords[2]) : 0;
                    if (b && (!a || a !== b)) {
                        mask[i + dimsU * j] = { material: b, normal: -1 };
                    }
                    else {
                        mask[i + dimsU * j] = null;
                    }
                }
            }
            mergeMask(quads, mask, dimsU, dimsV, axis, slice);
        }
    }
    return quads;
}
function generateQuadsForVoxelBox(primitive) {
    const dims = [
        Math.max(1, Math.round(primitive.size?.[0] ?? 1)),
        Math.max(1, Math.round(primitive.size?.[1] ?? 1)),
        Math.max(1, Math.round(primitive.size?.[2] ?? 1)),
    ];
    return generateGreedyQuads(primitive.voxels ?? [], dims);
}
//# sourceMappingURL=greedy-mesher.js.map