Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decompressing Texture in Viewer #367

Open
KuoFengYuan opened this issue Nov 14, 2024 · 3 comments
Open

Decompressing Texture in Viewer #367

KuoFengYuan opened this issue Nov 14, 2024 · 3 comments

Comments

@KuoFengYuan
Copy link

Hi! If I compress the file into a texture format according to the method in this paper to reduce model size, should I start from the loader to decompress it in the viewer?

@KuoFengYuan
Copy link
Author

KuoFengYuan commented Nov 18, 2024

Hi, I have already written a decompression parser that returns a blob format of the 3DGS PLY file. I want to directly use your parser to convert and render the results, but currently, I've only converted it into a splat array. Could you please guide me on how to render the result?
My code:

  try {
    const splats = await decompressor.decompress(compressDir);
    console.log('decompress:', splats);
    const plySaver = new PlySaver(splats, 3);
    plySaver.extractData();
    plySaver.prepareVertices();
    const plyBuffer = plySaver.save();  // Get the blob
    const reader = new FileReader();

    reader.onload = function(event) {
        const arrayBuffer = event.target.result;
        const splatArray = GaussianSplats3D.PlyParser.parseToUncompressedSplatArray(arrayBuffer,0);
        console.log(splatArray);
    };

    reader.readAsArrayBuffer(plyBuffer);

  } catch (err) {
    console.error('decompress fail:', err);
  }
})();

splatArray:
image

@mkkellogg
Copy link
Owner

You would probably need to update the PLY loader code to decompress the data. Specifically at this line:

return PlyParser.parseToUncompressedSplatArray(plyFileData, outSphericalHarmonicsDegree);

The file data would be in plyFileData and it would need to be decompressed before being passed to PlyParser.parseToUncompressedSplatArray()

@KuoFengYuan
Copy link
Author

Hello, I have implemented the functionality to decompress PNGs, insert data into the splat buffer, and render the restored information.
I would like to ask how I can progressively load the scene, similar to the progressiveLoad feature. Thank you!

My code in viewer.js:

async addSplatSceneFromBuffer(input, options = {}) {
    if (this.isLoadingOrUnloading()) {
        throw new Error('Cannot add splat scene while another load or unload is already in progress.');
    }

    if (this.isDisposingOrDisposed()) {
        throw new Error('Cannot add splat scene after dispose() is called.');
    }

    const showLoadingUI = options.showLoadingUI ?? true;

    let loadingUITaskId = null;
    if (showLoadingUI) {
        this.loadingSpinner.removeAllTasks();
        loadingUITaskId = this.loadingSpinner.addTask('Processing...');
    }

    const hideLoadingUI = () => {
        this.loadingProgressBar.hide();
        this.loadingSpinner.removeAllTasks();
    };

    const onProgressUIUpdate = (percentComplete, percentCompleteLabel, loaderStatus) => {
        if (showLoadingUI) {
            const suffix = percentCompleteLabel ? `: ${percentCompleteLabel}` : '...';
            const message = loaderStatus === LoaderStatus.Processing
                ? `Processing${suffix}`
                : 'Ready!';
            this.loadingSpinner.setMessageForTask(loadingUITaskId, message);
        }
    };

    const onProgress = (percentComplete, percentCompleteLabel, loaderStatus) => {
        onProgressUIUpdate(percentComplete, percentCompleteLabel, loaderStatus);
        if (options.onProgress) options.onProgress(percentComplete, percentCompleteLabel, loaderStatus);
    };

    try {
        console.time('Total Time'); // Start total time measurement

        let arrayBuffer;

        if (typeof input === 'string') {
            // If the input is a directory path, process the compressed directory.
            arrayBuffer = await this.processCompressedDirectory(input);
        } else if (input instanceof ArrayBuffer) {
            // If the input is an ArrayBuffer, use it directly.
            arrayBuffer = input;
        } else {
            throw new Error('Invalid input type: must be either an ArrayBuffer or a directory path string.');
        }

        console.time('Splat Buffer Add Time'); // Start splat buffer addition time
        const addSplatBufferOptions = {
            rotation: options.rotation || [0, 0, 0, 1],
            position: options.position || [0, 0, 0],
            scale: options.scale || [1, 1, 1],
            splatAlphaRemovalThreshold: options.splatAlphaRemovalThreshold,
        };
        await this.addSplatBuffers([arrayBuffer], [addSplatBufferOptions], true, true, showLoadingUI);
        console.timeEnd('Splat Buffer Add Time'); // End splat buffer addition time

        console.timeEnd('Total Time'); // End total time measurement

        hideLoadingUI();


    } catch (error) {
        hideLoadingUI();
        console.error('Failed to add splat scene:', error);
        throw error;
    }
}

/**
 * Decompress and process a compressed directory to generate a PLY buffer.
 * @param {string} compressDir - The path to the compressed directory.
 * @returns {Promise<ArrayBuffer>} - The generated PLY ArrayBuffer.
 */
async processCompressedDirectory(compressDir) {
    const decompressor = new Decompressor();

    return delayedExecute(() => {
        // Decompress the data from the compressed directory
        console.time('Decompression Time (processCompressedDirectory)');
        return decompressor.decompress(compressDir);
    })
    .then((splats) => {
        console.timeEnd('Decompression Time (processCompressedDirectory)'); // End decompression time
        console.time('splatBufferGenerator Time (processCompressedDirectory)'); // Start PLY conversion time

        // Assuming PngSaver is responsible for processing the decompressed splats
        const PngSav = new PngSaver(splats, 2);
        // Extract and parse the data into uncompressed splats
        const uncompressedSplats = PngSav.parseToUncompressedSplats();
        const splatBufferGenerator = SplatBufferGenerator.getStandardGenerator();
        // Generate the processed buffer from the uncompressed splats
        const processedBuffer = splatBufferGenerator.generateFromUncompressedSplatArray(uncompressedSplats);
        console.timeEnd('splatBufferGenerator Time (processCompressedDirectory)'); // End PLY conversion time


        return processedBuffer;
    });
}

@KuoFengYuan KuoFengYuan reopened this Nov 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants