Skip to content

Commit

Permalink
Merge pull request #89 from mkkellogg/feature/dynamic-transforms
Browse files Browse the repository at this point in the history
Dynamic transforms for splat scenes
  • Loading branch information
mkkellogg authored Dec 27, 2023
2 parents 59367d7 + 57c3e18 commit 3c05854
Show file tree
Hide file tree
Showing 22 changed files with 979 additions and 424 deletions.
31 changes: 16 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const viewer = new GaussianSplats3D.Viewer({
'initialCameraPosition': [-1, -4, 6],
'initialCameraLookAt': [0, 4, 0]
});
viewer.loadFile('<path to .ply, .ksplat, or .splat file>', {
viewer.addSplatScene('<path to .ply, .ksplat, or .splat file>', {
'splatAlphaRemovalThreshold': 5,
'showLoadingSpinner': true,
'position': [0, 1, 0],
Expand All @@ -134,24 +134,24 @@ Viewer parameters
| `initialCameraLookAt` | The initial focal point of the camera and center of the camera's orbit (only used when the viewer uses its own camera).
<br>

Parameters for `loadFile()`
Parameters for `addSplatScene()`
<br>

| Parameter | Purpose
| --- | ---
| `splatAlphaRemovalThreshold` | Tells `loadFile()` to ignore any splats with an alpha less than the specified value (valid range: 0 - 255). Defaults to `1`.
| `splatAlphaRemovalThreshold` | Tells `addSplatScene()` to ignore any splats with an alpha less than the specified value (valid range: 0 - 255). Defaults to `1`.
| `showLoadingSpinner` | Displays a loading spinner while the scene is loading. Defaults to `true`.
| `position` | Position of the scene, acts as an offset from its default position. Defaults to `[0, 0, 0]`.
| `rotation` | Rotation of the scene represented as a quaternion, defaults to `[0, 0, 0, 1]` (identity quaternion).
| `scale` | Scene's scale, defaults to `[1, 1, 1]`.

<br>

`Viewer` can also load multiple scenes simultaneously with the `loadFiles()` function:
`Viewer` can also load multiple scenes simultaneously with the `addSplatScenes()` function:
```javascript
import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d';

viewer.loadFiles([{
viewer.addSplatScenes([{
'path': '<path to first .ply, .ksplat, or .splat file>',
'splatAlphaRemovalThreshold': 20
},
Expand All @@ -167,27 +167,27 @@ viewer.loadFiles([{
});
```

The `loadFile()` and `loadFiles()` methods will accept the original `.ply` files, standard `.splat` files, and my custom `.ksplat` files.
The `addSplatScene()` and `addSplatScenes()` methods will accept the original `.ply` files, standard `.splat` files, and my custom `.ksplat` files.

<br>

### Integrating THREE.js scenes
You can integrate your own Three.js scene into the viewer if you want rendering to be handled for you. Just pass a Three.js scene object as the `scene` parameter to the constructor:
You can integrate your own Three.js scene into the viewer if you want rendering to be handled for you. Just pass a Three.js scene object as the `threeScene` parameter to the constructor:
```javascript
import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d';
import * as THREE from 'three';

const scene = new THREE.Scene();
const threeScene = new THREE.Scene();
const boxColor = 0xBBBBBB;
const boxGeometry = new THREE.BoxGeometry(2, 2, 2);
const boxMesh = new THREE.Mesh(boxGeometry, new THREE.MeshBasicMaterial({'color': boxColor}));
boxMesh.position.set(3, 2, 2);
scene.add(boxMesh);
threeScene.add(boxMesh);

const viewer = new GaussianSplats3D.Viewer({
'scene': scene,
'threeScene': threeScene,
});
viewer.loadFile('<path to .ply, .ksplat, or .splat file>')
viewer.addSplatScene('<path to .ply, .ksplat, or .splat file>')
.then(() => {
viewer.start();
});
Expand All @@ -201,11 +201,11 @@ A "drop-in" mode for the viewer is also supported. The `DropInViewer` class enca
import * as GaussianSplats3D from '@mkkellogg/gaussian-splats-3d';
import * as THREE from 'three';

const scene = new THREE.Scene();
const threeScene = new THREE.Scene();
const viewer = new GaussianSplats3D.DropInViewer({
'gpuAcceleratedSort': true
});
viewer.addScenesFromFiles([{
viewer.addSplatScenes([{
'path': '<path to .ply, .ksplat, or .splat file>'
'splatAlphaRemovalThreshold': 5
},
Expand All @@ -216,7 +216,7 @@ viewer.addScenesFromFiles([{
'position': [0, -2, -1.2]
}
]);
scene.add(viewer);
threeScene.add(viewer);

```
<br>
Expand Down Expand Up @@ -258,7 +258,7 @@ const viewer = new GaussianSplats3D.Viewer({
'sharedMemoryForWorkers': true,
'integerBasedSort': true
});
viewer.loadFile('<path to .ply, .ksplat, or .splat file>')
viewer.addSplatScene('<path to .ply, .ksplat, or .splat file>')
.then(() => {
requestAnimationFrame(update);
});
Expand All @@ -284,6 +284,7 @@ Advanced `Viewer` parameters
| `halfPrecisionCovariancesOnGPU` | Tells the viewer to use 16-bit floating point values when storing splat covariance data in textures, instead of 32-bit. Defaults to `true`.
| `sharedMemoryForWorkers` | Tells the viewer to use shared memory via a `SharedArrayBuffer` to transfer data to and from the sorting web worker. If set to `false`, it is recommended that `gpuAcceleratedSort` be set to `false` as well. Defaults to `true`.
| `integerBasedSort` | Tells the sorting web worker to use the integer versions of relevant data to compute the distance of splats from the camera. Since integer arithmetic is faster than floating point, this reduces sort time. However it can result in integer overflows in larger scenes so it should only be used for small scenes. Defaults to `true`.
| `dynamicScene` | Tells the viewer to not make any optimizations that depend on the scene being static. Additionally all splat data retrieved from the viewer's splat mesh will not have their respective scene transform applied to them by default.
<br>

### Creating KSPLAT files
Expand Down
Binary file added demo/assets/images/dynamic_scenes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions demo/dropin.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@
return camera;
}

function setupScene() {
const scene = new THREE.Scene();
function setupThreeScene() {
const threeScene = new THREE.Scene();
const boxColor = 0xBBBBBB;
const boxGeometry = new THREE.BoxGeometry(2, 2, 2);
const boxMesh = new THREE.Mesh(boxGeometry, new THREE.MeshBasicMaterial({'color': boxColor}));
scene.add(boxMesh);
threeScene.add(boxMesh);
boxMesh.position.set(3, 2, 2);
return scene;
return threeScene;
}

function setupControls(camera, renderer) {
Expand All @@ -88,11 +88,11 @@

const {renderer, renderWidth, renderHeight} = setupRenderer();
const camera = setupCamera(renderWidth, renderHeight);
const scene = setupScene();
const threeScene = setupThreeScene();
const controls = setupControls(camera, renderer);

const viewer = new GaussianSplats3D.DropInViewer();
viewer.addScenesFromFiles([
viewer.addSplatScenes([
{
'path': 'assets/data/garden/garden.ksplat',
'splatAlphaRemovalThreshold': 20,
Expand All @@ -105,13 +105,13 @@
'splatAlphaRemovalThreshold': 20,
}
], true);
scene.add(viewer);
threeScene.add(viewer);

requestAnimationFrame(update);
function update() {
requestAnimationFrame(update);
controls.update();
renderer.render(scene, camera);
renderer.render(threeScene, camera);
}
</script>
</body>
Expand Down
91 changes: 91 additions & 0 deletions demo/dynamic_scenes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<!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 Splats - Dynamic scenes example</title>
<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 viewer = new GaussianSplats3D.Viewer({
'cameraUp': [0, -1, -0.54],
'initialCameraPosition': [-7.14242, -2.25111, -2.36519],
'initialCameraLookAt': [1.52976, 2.27776, 1.65898],
'dynamicScene': true
});
viewer.addSplatScenes([
{
'path': 'assets/data/garden/garden.ksplat',
'splatAlphaRemovalThreshold': 20,
},
{
'path': 'assets/data/bonsai/bonsai_trimmed.ksplat',
'splatAlphaRemovalThreshold': 20,
},
{
'path': 'assets/data/bonsai/bonsai_trimmed.ksplat',
'splatAlphaRemovalThreshold': 20,
}
], true).then(() => {
viewer.start();
})

const bonsaiCount = 2;
const bonsaiStartIndex = 1;
const rotationAxis = new THREE.Vector3(0, -1, -0.6).normalize();
const baseQuaternion = new THREE.Quaternion(-0.147244, -0.07617, 0.14106, 0.9760);
const rotationQuaternion = new THREE.Quaternion();
const quaternion = new THREE.Quaternion();
const orbitCenter = new THREE.Vector3(0.416161, 1.385, 1.145);
const horizontalOffsetVector = new THREE.Vector3();
const position = new THREE.Vector3();
const scale = new THREE.Vector3(1.25, 1.25, 1.25);

let startTime = performance.now() / 1000.0;
requestAnimationFrame(update);
function update() {
requestAnimationFrame(update);
const timeDelta = performance.now() / 1000.0 - startTime;
for (let i = bonsaiStartIndex; i < bonsaiStartIndex + bonsaiCount; i++) {
const angle = timeDelta * 0.25 + (Math.PI * 2) / i;
const height = Math.cos(timeDelta + (Math.PI * 2) / i) * 0.5 + 3;

rotationQuaternion.setFromAxisAngle(rotationAxis, angle);
horizontalOffsetVector.set(3, 0, 0).applyQuaternion(rotationQuaternion);
position.copy(rotationAxis).multiplyScalar(height).add(horizontalOffsetVector).add(orbitCenter);
quaternion.copy(baseQuaternion).premultiply(rotationQuaternion);

const splatScene = viewer.getSplatScene(i);
splatScene.position.copy(position);
splatScene.quaternion.copy(quaternion);
splatScene.scale.copy(scale);
}
}
</script>
</body>

</html>
5 changes: 2 additions & 3 deletions demo/garden.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@
const viewer = new GaussianSplats3D.Viewer({
'cameraUp': [0, -1, -0.54],
'initialCameraPosition': [-3.15634, -0.16946, -0.51552],
'initialCameraLookAt': [1.52976, 2.27776, 1.65898],
'halfPrecisionCovariancesOnGPU': true
'initialCameraLookAt': [1.52976, 2.27776, 1.65898]
});
let path = 'assets/data/garden/garden';
path += isMobile() ? '.ksplat' : '_high.ksplat';
viewer.loadFile(path)
viewer.addSplatScene(path)
.then(() => {
viewer.start();
});
Expand Down
6 changes: 5 additions & 1 deletion demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
border-radius: 7px;
border: #bbbbbb 1px solid;
background-color: #f1f1f1;
width: 310px;
width: 220px;
margin-left: 8px;
margin-right: 8px;
}
Expand Down Expand Up @@ -562,6 +562,10 @@
<img src="assets/images/stump.png" class="demo-scene-panel-image">
<span class="small-title">Stump</span>
</div>
<div class="demo-scene-panel" onclick="openDemo('dynamic_scenes')">
<img src="assets/images/dynamic_scenes.png" class="demo-scene-panel-image">
<span class="small-title">Dynamic scenes</span>
</div>
</div>
</div>
<br>
Expand Down
2 changes: 1 addition & 1 deletion demo/stump.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
});
let path = 'assets/data/stump/stump';
path += isMobile() ? '.ksplat' : '_high.ksplat';
viewer.loadFile(path)
viewer.addSplatScene(path)
.then(() => {
viewer.start();
});
Expand Down
65 changes: 0 additions & 65 deletions demo/test.html

This file was deleted.

2 changes: 1 addition & 1 deletion demo/truck.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
});
let path = 'assets/data/truck/truck';
path += isMobile() ? '.ksplat' : '_high.ksplat';
viewer.loadFile(path)
viewer.addSplatScene(path)
.then(() => {
viewer.start();
});
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"type": "git",
"url": "https://github.com/mkkellogg/GaussianSplat3D"
},
"version": "0.1.11",
"version": "0.2.0",
"description": "Three.js-based 3D Gaussian splat viewer",
"module": "build/gaussian-splats-3d.module.js",
"main": "build/gaussian-splats-3d.umd.cjs",
Expand Down
Loading

0 comments on commit 3c05854

Please sign in to comment.