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
|
import { Video as BaseVideo, type FrameTime, type InitConfig } from '$/lib/Player/Video';
import * as THREE from 'three';
import type { OrbitControls } from 'three/examples/jsm/Addons.js';
export type Proxy<T> = T
export const OnceCell = <T>(create: () => T): Proxy<T> => {
let value = null as unknown as T;
let created = false;
let createOnce = (): T extends object ? T : never => {
// @ts-ignore
if (created) return value; else return (created = true, value = create())
}
return new Proxy({
get value() {
return createOnce()
}
}, {
get(_, ...args) {
return Reflect.get(createOnce(), ...args)
},
set(_, ...args) {
return Reflect.set(createOnce(), ...args)
},
has(_, ...args) {
return Reflect.has(createOnce(), ...args)
},
deleteProperty(_, ...args) {
return Reflect.deleteProperty(createOnce(), ...args)
},
isExtensible(_, ...args) {
return Reflect.isExtensible(createOnce(), ...args)
},
ownKeys(_, ...args) {
return Reflect.ownKeys(createOnce(), ...args)
},
defineProperty(_, ...args) {
return Reflect.defineProperty(createOnce(), ...args)
},
getOwnPropertyDescriptor(_, ...args) {
return Reflect.getOwnPropertyDescriptor(createOnce(), ...args)
},
preventExtensions(_, ...args) {
return Reflect.preventExtensions(createOnce(), ...args)
},
getPrototypeOf(_, ...args) {
return Reflect.getPrototypeOf(createOnce(), ...args)
},
setPrototypeOf(_, ...args) {
return Reflect.setPrototypeOf(createOnce(), ...args)
},
apply(_, ...args) {
type F = (this: any, ...args: any[]) => any
return Reflect.apply(createOnce() as unknown as T extends F ? F : never, ...args)
},
construct(_, ...args) {
type F = (this: any, ...args: any[]) => any
return Reflect.construct(createOnce() as unknown as T extends F ? F : never, ...args)
},
}) as Proxy<T>
}
export default abstract class ThreeVideo extends BaseVideo {
protected abstract ctx: CanvasRenderingContext2D
protected scene!: THREE.Scene;
protected camera!: THREE.PerspectiveCamera;
protected renderer!: THREE.WebGLRenderer;
protected threeCanvas!: HTMLCanvasElement;
protected orbitControls?: OrbitControls;
public async init(_config: InitConfig): Promise<void> {
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75, this.w / this.h, 0.1, 1000);
const canvas = this.threeCanvas = document.createElement('canvas');
canvas.width = this.canvas.width
canvas.height = this.canvas.height
canvas.style.opacity = "0"
canvas.style.position = "fixed";
canvas.style.top = "1000vh"
canvas.style.left = "1000vw"
document.body.appendChild(canvas)
this.renderer = new THREE.WebGLRenderer({
canvas: canvas,
alpha: true,
powerPreference: 'high-performance',
});
this.renderer.setSize(this.w, this.h);
this.renderer.setAnimationLoop(() => this.renderScene());
}
public renderScene(ctx?: CanvasRenderingContext2D) {
if (this.orbitControls)
this.orbitControls.update()
this.renderer.render(this.scene, this.camera)
if (ctx)
ctx.drawImage(this.threeCanvas, 0, 0)
}
public cleanup(): void {
this.renderer.dispose()
this.threeCanvas.remove()
}
}
|