92 lines
2.6 KiB
TypeScript
92 lines
2.6 KiB
TypeScript
import * as THREE from "three";
|
|
|
|
export type VolatileGeometry = {
|
|
mesh: THREE.Mesh,
|
|
}
|
|
|
|
export type VolatileGeometryBaseOptions = {
|
|
color: THREE.ColorRepresentation,
|
|
}
|
|
|
|
|
|
export type VolatileGeometryPointOptions = VolatileGeometryBaseOptions & {
|
|
kind: 'point',
|
|
size: number,
|
|
}
|
|
|
|
export type VolatileGeometryCicleOptions = VolatileGeometryBaseOptions & {
|
|
kind: 'circle',
|
|
radius: number,
|
|
thickness: number,
|
|
}
|
|
|
|
export type VolatileGeometryOptions = VolatileGeometryPointOptions | VolatileGeometryCicleOptions;
|
|
|
|
export class VolatileGeometryHelper {
|
|
|
|
private scene: THREE.Scene;
|
|
private camera: THREE.PerspectiveCamera | THREE.OrthographicCamera;
|
|
|
|
private readonly baseMaterial = new THREE.MeshBasicMaterial({ color: 'red' });
|
|
|
|
private readonly markers: Record<string, VolatileGeometry> = {};
|
|
|
|
constructor(scene: THREE.Scene, camera: THREE.PerspectiveCamera | THREE.OrthographicCamera) {
|
|
this.scene = scene;
|
|
this.camera = camera;
|
|
}
|
|
|
|
private createGeometry(options: VolatileGeometryOptions): THREE.BufferGeometry {
|
|
switch (options.kind) {
|
|
case 'point':
|
|
return new THREE.SphereGeometry(options.size);
|
|
case 'circle':
|
|
return new THREE.TorusGeometry(options.radius, options.thickness * options.radius);
|
|
default:
|
|
throw new Error('Unknown volatile geometry type');
|
|
}
|
|
}
|
|
|
|
private ensure(id: string, options: VolatileGeometryOptions): VolatileGeometry {
|
|
if (!this.markers[id]) {
|
|
const material = this.baseMaterial.clone();
|
|
material.color.set(options.color);
|
|
this.markers[id] = {
|
|
mesh: new THREE.Mesh(
|
|
this.createGeometry(options),
|
|
material,
|
|
),
|
|
};
|
|
this.scene.add(this.markers[id].mesh);
|
|
}
|
|
|
|
return this.markers[id];
|
|
}
|
|
|
|
private disposeGeometry(id: string) {
|
|
const point = this.markers[id];
|
|
if (point) {
|
|
this.scene.remove(point.mesh);
|
|
point.mesh.geometry.dispose();
|
|
delete (this.markers[id]);
|
|
}
|
|
}
|
|
|
|
public dispose() {
|
|
for (const id in this.markers)
|
|
this.disposeGeometry(id);
|
|
}
|
|
|
|
public set(id: string, position: THREE.Vector3Like, options: VolatileGeometryOptions) {
|
|
const point = this.ensure(id, options);
|
|
|
|
// additional actions
|
|
switch (options.kind) {
|
|
case 'circle':
|
|
point.mesh.lookAt(this.camera.position);
|
|
break;
|
|
}
|
|
|
|
point.mesh.position.copy(position);
|
|
}
|
|
} |