File size: 3,096 Bytes
ebb3bda 537f2af ebb3bda ec3121c 537f2af 95af024 ec3121c cc654e9 bdef08e 1b5e137 ec3121c cc654e9 95af024 31a2d08 70a459f ec3121c 95af024 31a2d08 ec3121c 95af024 ec3121c 95af024 ec3121c 95af024 ec3121c 70a459f 95af024 1b5e137 bdef08e 70a459f cc654e9 70a459f 95af024 ec3121c cc654e9 ebb3bda c9731fb 70a459f ebb3bda 3b7903d ebb3bda 3b7903d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
import type { IViewer } from "./IViewer";
import * as SPLAT from "gsplat";
export class SplatViewer implements IViewer {
canvas: HTMLCanvasElement;
renderer: SPLAT.WebGLRenderer;
scene: SPLAT.Scene;
camera: SPLAT.Camera;
controls: SPLAT.OrbitControls;
disposed: boolean = false;
constructor(canvas: HTMLCanvasElement) {
this.canvas = canvas;
this.renderer = new SPLAT.WebGLRenderer(canvas);
this.scene = new SPLAT.Scene();
this.camera = new SPLAT.Camera();
this.controls = new SPLAT.OrbitControls(this.camera, canvas);
this.controls.orbitSpeed = 3.0;
this.handleResize = this.handleResize.bind(this);
}
async loadScene(url: string, loadingBarCallback?: (progress: number) => void) {
if (url.endsWith(".splat")) {
await SPLAT.Loader.LoadAsync(url, this.scene, (progress) => {
loadingBarCallback?.(progress);
});
} else if (url.endsWith(".ply")) {
await SPLAT.PLYLoader.LoadAsync(url, this.scene, (progress) => {
loadingBarCallback?.(progress);
});
} else {
throw new Error("Unsupported file format");
}
const frame = () => {
this.controls.update();
this.renderer.render(this.scene, this.camera);
if (!this.disposed) {
requestAnimationFrame(frame);
}
};
this.disposed = false;
this.handleResize();
window.addEventListener("resize", this.handleResize);
requestAnimationFrame(frame);
}
handleResize() {
this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
}
dispose() {
window.removeEventListener("resize", this.handleResize);
this.controls.dispose();
this.renderer.dispose();
this.disposed = true;
}
async capture(): Promise<string | null> {
return new Promise((resolve) => {
requestAnimationFrame(() => {
const offscreenCanvas = document.createElement("canvas");
offscreenCanvas.width = 512;
offscreenCanvas.height = 512;
const offscreenContext = offscreenCanvas.getContext("2d") as CanvasRenderingContext2D;
const x = (this.canvas.width - offscreenCanvas.width) / 2;
const y = (this.canvas.height - offscreenCanvas.height) / 2;
offscreenContext.drawImage(
this.canvas,
x,
y,
offscreenCanvas.width,
offscreenCanvas.height,
0,
0,
offscreenCanvas.width,
offscreenCanvas.height
);
const dataUrl = offscreenCanvas.toDataURL("image/png");
offscreenCanvas.remove();
resolve(dataUrl);
});
});
}
getStats(): { name: string; value: any }[] {
return [];
}
}
|