mkkellogg / GaussianSplats3D

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

If x y z of the position is too large, it will not display properly #336

Open hisayan opened 2 months ago

hisayan commented 2 months ago

I would like to display 3DGS on the surface of the earth at earth-centered coordinates. so the position (x,y,z) is too large.

then I faced two problems.

1) That model will have a lower resolution.

2) When I change the angle of view with the mouse, the model will shake for a while. (Zoom up and down operations are normal)

largeposition

How can I solve this problem?

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <title>3D Gaussian Splat Demo - Garden</title>
  <script type="text/javascript" src="js/util.js"></script>
  <script type="importmap">
    {
        "imports": {
            "three": "./lib/three.module.js",
            "@mkkellogg/gaussian-splats-3d": "./lib/gaussian-splats-3d.module.js"
        }
    }
  </script>
  <style>

    body {
      background-color: #000000;
      height: 100vh;
      margin: 0px;
    }

  </style>

</head>

<body>
  <script type="module">
    import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d';
    import * as THREE from 'three';

    const urlParams = new URLSearchParams(window.location.search);
    const mode = parseInt(urlParams.get('mode')) || 0;

    const viewer = new GaussianSplats3D.Viewer({
      'cameraUp': [0.01933, -0.75830, -0.65161],
      'initialCameraPosition': [-3765742.4889918035, 3657621.71103427,  3610490.3155687014],
      'initialCameraLookAt': [-3765742.4889918035, 3657621.71103427,  3610505.3155687014],
      // 'initialCameraLookAt': [1.52976, 2.27776, 1.65898],
      'sphericalHarmonicsDegree': 2
    });
    let path = 'assets/data/bonsai/bonsai' + (mode ? '_high' : '') + '.ksplat';
    viewer.addSplatScene(path, {
      'progressiveLoad': false,
      position: [-3765742.4889918035, 3657621.71103427,  3610505.3155687014]
    })
    .then(() => {
        viewer.start();
    });

  </script>
</body>

</html>
mkkellogg commented 2 months ago

Ah, so this is a well known issue. There are a couple of things you can try:

  1. Set the Viewer parameter integerBasedSort to false.
  2. Experiment with the Viewer parameter splatSortDistanceMapPrecision. The default value is 16 (16-bit) but at that level it struggles with large scenes. Try bumping it up to 20 or maybe a bit higher. (There is a performance cost to increasing that value).

At some point, my viewer simply can't handle positions or scene dimensions that are too large though; I think the example you pasted above is close or possibly over that limit.

hisayan commented 2 months ago

Thank you for your kindness.

I tried to add parameters 'integerBasedSort' and 'splatSortDistanceMapPrecision', but it could'nt work well.

By the way, I set the position of the splatMesh of threejs 3Dobject's property then it worked well. I wonder that what different is the addSplatScene parameter position and the position of the splatMesh of threejs. However, when I set the dynamicScene to true then it didn't worked as is should.

    const viewer = new GaussianSplats3D.Viewer({
      'cameraUp': [0.01933, -0.75830, -0.65161],
      'initialCameraPosition': [-3765742.4889918035, 3657621.71103427,  3610490.3155687014],
      'initialCameraLookAt': [-3765742.4889918035, 3657621.71103427,  3610505.3155687014],
      // 'initialCameraLookAt': [1.52976, 2.27776, 1.65898],
      'sphericalHarmonicsDegree': 2,
      // dynamicScene: true
    });
    let path = 'assets/data/bonsai/bonsai' + (mode ? '_high' : '') + '.ksplat';
    viewer.addSplatScene(path, {
      'progressiveLoad': false,
      // position: [-3765742.4889918035, 3657621.71103427,  3610505.3155687014]
    })
    .then(() => {
        viewer.start();
        const splatMesh = viewer.getSplatMesh();
        splatMesh.position.set(-3765742.4889918035, 3657621.71103427,  3610505.3155687014)
    });
mkkellogg commented 1 month ago

Ah the reason that it seems to work when you set the position of the splat mesh after the viewer starts when dynamicMode is false is that changes to the splat mesh's position, orientation or scale are only applied if dynamicMode is true.

hisayan commented 1 month ago

Thanks.

Here is my prototype. https://3dgs.console.minc.app/3dgs/nakajima

I implemented this with dynamicMode = false, but I want to display multiple 3DGS at the same time, preferably expressed with dymnamicScene = true.

mkkellogg commented 1 month ago

Sorry for the late reply. I think the only way you'll be able to display multiple 3DGS files using such a large scale is if you use multiple instances of GaussianSplats3D.Viewer and set their position by changing the position property of the Viewer.splatMesh directly (since it is a three.js Object3D). There still might be issues after that if the camera's position is also using large numbers.

hisayan commented 1 month ago

Thanks for your advice. I'll give it a try.