Move web/ to javascript/ and declare it via [tool.comfy] web. Rename the seven third-party bundles (playcanvas, spark, three.js, gsplat, OrbitControls, TrackballControls) to .mjs. Every reference to them is inside the HTML viewers, but ComfyUI auto-imports **/*.js under the web dir into the shared browser realm, so ~8MB of vendor code was being evaluated in the main page on every startup -- and with it 36 collision errors: document.body injection, document-level listeners, unguarded message listeners and self.onmessage writes. The importmap values, script srcs and three.module's internal ./three.core ref are rewritten to match. DisplayName becomes "GaussianPack": the namespace enforced on registerExtension names is derived from it, and "ComfyUI-GaussianPack" made that prefix invalid. The analysis extension is renamed to match. js/gaussian_preview.js hooked "PlyPreviewLoadGaussianPLYEnhance", a node id that appears nowhere in this repo, so the PLY dropdown auto-refresh had never run; it now targets LoadPLY and LoadPLYOutput, the two nodes that actually carry the ply_file widget. Guard its message listener on event.source. Asset seeding resolves the input directory through folder_paths.get_input_directory(), so it follows ComfyUI Desktop and --input-directory instead of writing into the code tree. comfy-test.toml moves to the current schema: [test.workflows] cuda (there is no "gpu" key -- the accelerator is named by backend, and the old spelling parsed to an empty list, so CUDA runners silently ran the full unfiltered set), an explicit [test.platforms] platforms allowlist (per-platform booleans are no longer supported), and the javascript level.
86 lines
3.1 KiB
JavaScript
86 lines
3.1 KiB
JavaScript
export function serializePly(data) {
|
|
const N = data.numPoints;
|
|
// Validate sizes
|
|
if (data.positions.length !== N * 3 ||
|
|
data.scales.length !== N * 3 ||
|
|
data.rotations.length !== N * 4 ||
|
|
data.alphas.length !== N ||
|
|
data.colors.length !== N * 3) {
|
|
throw new Error('[PLY ERROR] Invalid data sizes');
|
|
}
|
|
const shDim = Math.floor(data.sh.length / N / 3);
|
|
const D = 17 + shDim * 3;
|
|
// Create header
|
|
const header = [
|
|
'ply',
|
|
'format binary_little_endian 1.0',
|
|
`element vertex ${N}`,
|
|
'property float x',
|
|
'property float y',
|
|
'property float z',
|
|
'property float nx',
|
|
'property float ny',
|
|
'property float nz',
|
|
'property float f_dc_0',
|
|
'property float f_dc_1',
|
|
'property float f_dc_2',
|
|
...Array.from({ length: shDim * 3 }, (_, i) => `property float f_rest_${i}`),
|
|
'property float opacity',
|
|
'property float scale_0',
|
|
'property float scale_1',
|
|
'property float scale_2',
|
|
'property float rot_0',
|
|
'property float rot_1',
|
|
'property float rot_2',
|
|
'property float rot_3',
|
|
'end_header\n'
|
|
].join('\n');
|
|
// Prepare values array
|
|
const values = new Float32Array(N * D);
|
|
let outIdx = 0, i3 = 0, i4 = 0;
|
|
for (let i = 0; i < N; i++) {
|
|
// Position (x, y, z)
|
|
values[outIdx++] = data.positions[i3 + 0];
|
|
values[outIdx++] = data.positions[i3 + 1];
|
|
values[outIdx++] = data.positions[i3 + 2];
|
|
// Normals (nx, ny, nz) - always zero
|
|
values[outIdx++] = 0;
|
|
values[outIdx++] = 0;
|
|
values[outIdx++] = 0;
|
|
// Colors (r, g, b)
|
|
values[outIdx++] = data.colors[i3 + 0];
|
|
values[outIdx++] = data.colors[i3 + 1];
|
|
values[outIdx++] = data.colors[i3 + 2];
|
|
// Spherical harmonics
|
|
for (let j = 0; j < shDim; j++) {
|
|
values[outIdx++] = data.sh[(i * shDim + j) * 3 + 0];
|
|
}
|
|
for (let j = 0; j < shDim; j++) {
|
|
values[outIdx++] = data.sh[(i * shDim + j) * 3 + 1];
|
|
}
|
|
for (let j = 0; j < shDim; j++) {
|
|
values[outIdx++] = data.sh[(i * shDim + j) * 3 + 2];
|
|
}
|
|
// Alpha
|
|
values[outIdx++] = data.alphas[i];
|
|
// Scale (sx, sy, sz)
|
|
values[outIdx++] = data.scales[i3 + 0];
|
|
values[outIdx++] = data.scales[i3 + 1];
|
|
values[outIdx++] = data.scales[i3 + 2];
|
|
// Rotation (qw, qx, qy, qz)
|
|
values[outIdx++] = data.rotations[i4 + 3];
|
|
values[outIdx++] = data.rotations[i4 + 0];
|
|
values[outIdx++] = data.rotations[i4 + 1];
|
|
values[outIdx++] = data.rotations[i4 + 2];
|
|
i3 += 3;
|
|
i4 += 4;
|
|
}
|
|
// Combine header and values into final buffer
|
|
const headerBuffer = new TextEncoder().encode(header);
|
|
const finalBuffer = new ArrayBuffer(headerBuffer.length + values.buffer.byteLength);
|
|
const finalView = new Uint8Array(finalBuffer);
|
|
finalView.set(headerBuffer, 0);
|
|
finalView.set(new Uint8Array(values.buffer), headerBuffer.length);
|
|
return finalBuffer;
|
|
}
|