File size: 3,673 Bytes
ebb3bda
537f2af
ebb3bda
 
ec3121c
 
537f2af
95af024
 
 
62c50cd
ec3121c
cc654e9
9c554be
bdef08e
e7b5357
 
1b5e137
ec3121c
cc654e9
95af024
b95cc56
 
95af024
 
 
31a2d08
62c50cd
70a459f
 
ec3121c
 
9c554be
 
 
31a2d08
62c50cd
31a2d08
 
 
62c50cd
31a2d08
 
 
 
 
ec3121c
e7b5357
 
95af024
 
 
ec3121c
95af024
 
ec3121c
 
 
95af024
ec3121c
70a459f
 
 
95af024
1b5e137
bdef08e
70a459f
 
 
 
cc654e9
70a459f
 
95af024
 
ec3121c
cc654e9
 
ebb3bda
c9731fb
70a459f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ebb3bda
 
62c50cd
 
 
 
 
 
 
 
 
 
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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;
    splat: SPLAT.Splat | null;

    disposed: boolean = false;
    topoOnly: boolean = false;

    vertexCount: number = 0;

    constructor(canvas: HTMLCanvasElement) {
        this.canvas = canvas;

        this.renderer = new SPLAT.WebGLRenderer(canvas);
        this.renderer.renderProgram.outlineColor = new SPLAT.Color32(180, 180, 180);

        this.scene = new SPLAT.Scene();
        this.camera = new SPLAT.Camera();
        this.controls = new SPLAT.OrbitControls(this.camera, canvas);
        this.controls.orbitSpeed = 3.0;
        this.splat = null;

        this.handleResize = this.handleResize.bind(this);
    }

    async loadScene(url: string, loadingBarCallback?: (progress: number) => void, topoOnly?: boolean) {
        this.topoOnly = topoOnly ?? false;

        if (url.endsWith(".splat")) {
            this.splat = await SPLAT.Loader.LoadAsync(url, this.scene, (progress) => {
                loadingBarCallback?.(progress);
            });
        } else if (url.endsWith(".ply")) {
            this.splat = await SPLAT.PLYLoader.LoadAsync(url, this.scene, (progress) => {
                loadingBarCallback?.(progress);
            });
        } else {
            throw new Error("Unsupported file format");
        }

        this.vertexCount = this.splat.data.vertexCount;

        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);
            });
        });
    }

    setRenderMode(mode: string): void {
        if (!this.splat) return;

        if (mode === "wireframe") {
            this.splat.selected = true;
        } else {
            this.splat.selected = false;
        }
    }

    getStats(): { name: string; value: any }[] {
        return [];
    }
}