mkkellogg / GaussianSplats3D

Three.js-based implementation of 3D Gaussian splatting
MIT License
1.53k stars 198 forks source link

`AbortedPromiseError: Scene disposed` error in Next.js #325

Closed hyqshr closed 2 months ago

hyqshr commented 2 months ago

I am trying to load gaussian splat from a resource url in Next.js. But got error:

Error loading splat scenes: AbortedPromiseError: Scene disposed

Next.js: 14.2.3 gaussian-splats-3d: 0.4.4

Code (SplatsView copied from https://github.com/mkkellogg/GaussianSplats3D/issues/247):

'use client'

import * as THREE from "three";
import React, { useState, useEffect } from "react";
import * as GaussianSplats3D from "@mkkellogg/gaussian-splats-3d";

export function SplatsView({ sources, options }: { sources: Array<string>, options?: Array<any> }) {
    const [scene] = useState(() => new THREE.Scene())

    useEffect(() => {
        const viewer = new GaussianSplats3D.DropInViewer({
            sharedMemoryForWorkers: false,
            showLoadingUI: true,
            format: GaussianSplats3D.SceneFormat.Ply,
        });

        const addParams: Array<any> = sources.map((source: string, index: number) => {
            const params: any = {
                path: source
            };
            Object.assign(params, (options && options.length > index) ? options[index] : {});
            return params;
        });

        scene.add(viewer);

        viewer.addSplatScenes(addParams, false)
            .catch((err) => {
                console.log("Error loading splat scenes:", err);
            });

        return () => {
            viewer.dispose()
                .catch((err) => {
                    console.log("Error disposing of splats viewer:", err);
                });
        };
    }, []);

    return (<primitive object={scene} />);
}

export default function Page() {
  const splatURL = 'https://huggingface.co/datasets/runes/coolsplats/resolve/main/output.splat'

    return (
        <div>
            <SplatsView sources={[splatURL]} />
        </div>
    )
}

Thank you!

Stack trace:

Error loading splat scenes: AbortedPromiseError: Scene disposed
    at AbortablePromise.abortHandler (VM24892 gaussian-splats-3d.module.js:168:31)
    at AbortablePromise.abort (VM24892 gaussian-splats-3d.module.js:95:37)
    at AbortablePromise.eval [as abortHandler] (VM24892 gaussian-splats-3d.module.js:12281:37)
    at AbortablePromise.abort (VM24892 gaussian-splats-3d.module.js:95:37)
    at eval (VM24892 gaussian-splats-3d.module.js:12756:21)
    at Array.forEach (<anonymous>)
    at Viewer.dispose (VM24892 gaussian-splats-3d.module.js:12755:25)
    at DropInViewer.dispose (VM24892 gaussian-splats-3d.module.js:13417:28)
    at eval (page.tsx:34:20)
    at safelyCallDestroy (react-dom.development.js:20869:5)
    at commitHookEffectListUnmount (react-dom.development.js:21051:11)
    at invokePassiveEffectUnmountInDEV (react-dom.development.js:24033:13)
    at invokeEffectsInDev (react-dom.development.js:26852:9)
    at legacyCommitDoubleInvokeEffectsInDEV (react-dom.development.js:26829:5)
    at commitDoubleInvokeEffectsInDEV (react-dom.development.js:26816:7)
    at flushPassiveEffectsImpl (react-dom.development.js:26514:5)
    at flushPassiveEffects (react-dom.development.js:26438:14)
    at performSyncWorkOnRoot (react-dom.development.js:24870:32)
    at flushSyncWorkAcrossRoots_impl (react-dom.development.js:7758:13)
    at flushSyncWorkOnAllRoots (react-dom.development.js:7718:3)
    at commitRootImpl (react-dom.development.js:26369:3)
    at commitRoot (react-dom.development.js:26077:5)
    at commitRootWhenReady (react-dom.development.js:24749:3)
    at finishConcurrentRender (react-dom.development.js:24714:5)
    at performConcurrentWorkOnRoot (react-dom.development.js:24559:9)
    at workLoop (scheduler.development.js:256:34)
    at flushWork (scheduler.development.js:225:14)
    at MessagePort.performWorkUntilDeadline (scheduler.development.js:534:21)
mkkellogg commented 2 months ago

Is it an actual error or console logging statement? Because you likely have Next.js running in strict mode, it will load your react component, then immediately unload and then load again to test how durable it is. When it unloads your react component, the viewer will get disposed, but because it is already trying to load a scene, that load has to be aborted and that's why you're seeing the AbortablePromiseError. However, I'm guessing you're seeing it because of this code:

viewer.addSplatScenes(addParams, false)
    .catch((err) => {
        console.log("Error loading splat scenes:", err);
    });

If you take out that console.log statement, it might go away.

hyqshr commented 2 months ago

@mkkellogg Thank you for your reply!

Nothing is loaded in my page, and I got few errors:

image image
mkkellogg commented 2 months ago

Did you change GaussianSplats3D.Viewer back to GaussianSplats3D.DropInViewer ?

hyqshr commented 2 months ago

The above two error come from GaussianSplats3D.DropInViewer

Should I use GaussianSplats3D.Viewer or GaussianSplats3D.DropInViewer?

mkkellogg commented 2 months ago

You should be using GaussianSplats3D.DropInViewer, so it looks like you're fine there. When I run the code you pasted above in a Next.js project and I remove the line console.log("Error loading splat scenes:", err);, I don't see any errors and the splat scene loads fine.

hyqshr commented 2 months ago

That's weird,

I tried "@mkkellogg/gaussian-splats-3d": "^0.4.4" with next.js version 14.2.8, '14.2.4' and 13.4.19 it all does not load the scene.

It seems that they all abort download the .ply file

mkkellogg commented 2 months ago

It's probably worth checking -- Are you using your component under an R3F <Canvas> component somewhere?

mkkellogg commented 2 months ago

Also, you need to be adding all the other three.js components needed for rendering (camera, controls, etc.) yourself

aimehai commented 2 months ago

I'm new to both Three.js and Gaussian splats. Can you share your Next.js project? I can give you my email @mkkellogg

hyqshr commented 2 months ago

@mkkellogg No I am not using <Canvas> at all.

Will

<SplatsView sources={[splatURL]} />

Alone not able to render a view?

mkkellogg commented 2 months ago

Yeah the <Canvas> R3F element works similar to the way an HTML <canvas> works in standard three.js -- as the root rendering window. It serves as the container for standard three.js objects like the camera (which your example doesn't seem to have). Here's a simple example that I got to work:

'use client'

import { Canvas } from '@react-three/fiber'
import React from 'react';
import { SplatsView } from "@/components/canvas/SplatsView";
import { OrbitControls } from "@react-three/drei";

export default function Scene() {
  return (
    <React.StrictMode>
      <Canvas camera={{ near: 0.01, far: 1000 }}>
        <SplatsView
          sources={['https://huggingface.co/datasets/runes/coolsplats/resolve/main/output.splat']}
          options={[{ position: [0, 0, 0], scale: [2, 2, 2] }]}>
        </SplatsView>
        <OrbitControls />
      </Canvas>
    </React.StrictMode>
  )
}
hyqshr commented 2 months ago

It worked, thank you so much! I will dig in more about Three.js

mkkellogg commented 2 months ago

Great!