huggingface / gsplat.js

JavaScript Gaussian Splatting library.
MIT License
1.26k stars 77 forks source link

camera debug info #62

Closed VladimirKobranov closed 4 months ago

VladimirKobranov commented 4 months ago

Will be great to have window with camera position and rotation in scene in current moment.

Like from here: https://github.com/mkkellogg/GaussianSplats3D

Really helpful to set initial positions and rotations for each file.

TravisThomp commented 4 months ago

dat.gui is really good for adding this developer panel to your project. I can show you an example if you need. It works really nicely and is pretty simple to add :)

VladimirKobranov commented 4 months ago

Will be nice to see example for gsplat camera.

TravisThomp commented 4 months ago

This is based off the camera-updates example hope this helps :)

import * as SPLAT from "gsplat";
import * as dat from 'dat.gui';

const gui = new dat.GUI();

const canvas = document.getElementById("canvas") as HTMLCanvasElement;
const progressDialog = document.getElementById("progress-dialog") as HTMLDialogElement;
const progressIndicator = document.getElementById("progress-indicator") as HTMLProgressElement;

const renderer = new SPLAT.WebGLRenderer(canvas);
const scene = new SPLAT.Scene();
const camera = new SPLAT.Camera();

let cameraPosition = { x: 0, y: 0, z: 0 };
let cameraRotation = { x: 0, y: 0, z: 0 };

function setupGui() {
    let cameraFolder = gui.addFolder("Camera");
    let rotationFolder = cameraFolder.addFolder("Rotation");
    let positionFolder = cameraFolder.addFolder("Positon");

    positionFolder.add(cameraPosition, "x", -10, 10).step(0.1);
    positionFolder.add(cameraPosition, "y", -10, 10).step(0.1);
    positionFolder.add(cameraPosition, "z", -10, 10).step(0.1);

    rotationFolder.add(cameraRotation, "x", -10, 10).step(0.1);
    rotationFolder.add(cameraRotation, "y", -10, 10).step(0.1);
    rotationFolder.add(cameraRotation, "z", -10, 10).step(0.1);
}

async function main() {
    const url = "https://huggingface.co/datasets/dylanebert/3dgs/resolve/main/bonsai/bonsai-7k.splat";
    await SPLAT.Loader.LoadAsync(url, scene, (progress) => (progressIndicator.value = progress * 100));
    progressDialog.close();

    setupGui();

    const handleResize = () => {
        renderer.setSize(canvas.clientWidth, canvas.clientHeight);
    };

    const frame = () => {
        renderer.render(scene, camera);
        camera.position = new SPLAT.Vector3(cameraPosition.x, cameraPosition.y, cameraPosition.z);

        camera.rotation = SPLAT.Quaternion.FromEuler(new SPLAT.Vector3(cameraRotation.x, cameraRotation.y, cameraRotation.z));
        console.log(cameraPosition);

        requestAnimationFrame(frame);
    };

    handleResize();
    window.addEventListener("resize", handleResize);

    requestAnimationFrame(frame);
}

main();
VladimirKobranov commented 4 months ago

Hm, it's working, but in inverted way. Let me describe more:

You have your scene and your camera on it. You drag and rotate your camera on scene. And once you are happy with current view, you want to same it. And ( for simple example ) you want to manualy write whose coordinates somewhere to use them again.

Like this: init( camera.position(0, 0.5, 0.7); camera.rotation(0, 0.2, 0);

So thats why i need info about current camera transforms in debug window. It's kinda usefull to see stats at exact moment of time

TravisThomp commented 4 months ago

So, from what I'm understanding is that you want to be able to view the camera's position and rotation so you can save it for later correct?

VladimirKobranov commented 4 months ago

Correct. I think i sorted it. For vue.

<template>
  <div class="viewport">
    <canvas ref="canvas"></canvas>
    <div v-show="progress < 100 && !completed">
      <div class="prog d-flex flex-column justify-content-center">
        <div class="text-center">{{ progress }}%</div>
        <div class="text-center">Loading...</div>
      </div>
    </div>
    <div class="debug">
      <div>
        position:{{ cameraPosition}}
      </div>
      <div>
        rotation:{{ cameraRotation}}
      </div>
    </div>
  </div>
</template>

<script>
import * as SPLAT from "https://cdn.jsdelivr.net/npm/gsplat@latest";

export default {
  data() {
    return {
      progress: 0,
      completed: false,
      cameraPosition: null,
      cameraRotation: null,
    };
  },
  mounted() {
    this.initSplat();
  },
  methods: {
    async initSplat() {
      const canvas = this.$refs.canvas;

      const renderer = new SPLAT.WebGLRenderer(canvas);
      const scene = new SPLAT.Scene();
      const camera = new SPLAT.Camera();
      const controls = new SPLAT.OrbitControls(camera, canvas);

      const url =
          "https://huggingface.co/VladKobranov/splats/resolve/main/bicycle-noroad.splat";

      const updateProgress = (progress) => {
        this.progress = Math.floor(progress * 100);
      };

      const splat = await SPLAT.Loader.LoadAsync(url, scene, updateProgress);
      this.completed = true;
      // this.setupGui();

      const handleResize = () => {
        renderer.setSize(canvas.clientWidth, canvas.clientHeight);
      };

      const newPosition = new SPLAT.Vector3(1.5286581664888774, -1.1024285996791527, -1.7628278717300327);
      const newRotation = new SPLAT.Quaternion(-0.09540055501374875, -0.37249018228438835, -0.03852887843485292, 0.9223151976040317);
      camera.position = newPosition;
      camera.rotation = newRotation;

      const frame = () => {
        controls.update();
        renderer.render(scene, camera);

        this.cameraPosition = camera.position;
        this.cameraRotation = camera.rotation;
        requestAnimationFrame(frame);
      };

      handleResize();
      window.addEventListener("resize", handleResize);
      requestAnimationFrame(frame);
      console.log("camera position", camera.position);
      console.log("camera rotation", camera.rotation);

    },
  },
};
</script>
dylanebert commented 4 months ago

Glad you figured it out 👍