106 lines
3.1 KiB
TypeScript
106 lines
3.1 KiB
TypeScript
import type { Object3D, OrthographicCamera, PerspectiveCamera, Scene, Vector2Like, WebGLRenderer } from "three";
|
|
import { MeshCache } from "../layers/meshCache";
|
|
import { GeometryCache } from "../layers/geometryCache";
|
|
import type { Id } from "../types";
|
|
import { CircularFrustumIntersection, type HitResults } from "./circularFrustumIntersect";
|
|
import { CircularFrustum } from "./circularFrustum";
|
|
import './bvh';
|
|
import { ThreeHintDisplay } from "./ThreeHintDisplay";
|
|
import { model } from "../model/model";
|
|
import { Geometry } from "../backend/geometry/geometry";
|
|
import { meshToDto } from "../backend/dto";
|
|
|
|
export class SceneHelper {
|
|
|
|
private meshes: MeshCache | undefined;
|
|
|
|
public _hints: ThreeHintDisplay | undefined;
|
|
private camera: PerspectiveCamera | OrthographicCamera | undefined;
|
|
|
|
private mouseFrustum = new CircularFrustumIntersection(new CircularFrustum());
|
|
|
|
public initialize(
|
|
scene: Scene,
|
|
camera: PerspectiveCamera | OrthographicCamera,
|
|
renderer: WebGLRenderer,
|
|
) {
|
|
this._hints = new ThreeHintDisplay(scene, camera, renderer);
|
|
this.camera = camera;
|
|
|
|
this.meshes = new MeshCache(scene, new GeometryCache());
|
|
for (const id of Object.keys(model.solids)) {
|
|
const meshes = Geometry
|
|
.tessellateSolid(id)
|
|
.map(meshToDto);
|
|
// this.sync.addSolid(meshes[0]); // bottom
|
|
// this.sync.addSolid(meshes[3]); // front
|
|
for (const mesh of meshes)
|
|
this.meshes.addMesh(mesh.faceId, mesh);
|
|
}
|
|
}
|
|
|
|
public get hints(): ThreeHintDisplay {
|
|
if (!this._hints)
|
|
throw new Error('SceneHelper is not initiallized');
|
|
|
|
return this._hints;
|
|
}
|
|
|
|
public buildMouseFrustum(
|
|
mouseNormalized: Vector2Like,
|
|
screenSize: Vector2Like,
|
|
radius: number = 5,
|
|
): void {
|
|
if (!this.camera)
|
|
throw new Error('SceneHelper is not initiallized');
|
|
|
|
this.mouseFrustum.frustum.setFromScreenPoint(
|
|
mouseNormalized,
|
|
screenSize,
|
|
this.camera,
|
|
radius,
|
|
);
|
|
}
|
|
|
|
public hitTest(
|
|
mouseNormalized: Vector2Like,
|
|
screenSize: Vector2Like,
|
|
): HitResults {
|
|
this.buildMouseFrustum(mouseNormalized, screenSize);
|
|
|
|
return {
|
|
hits: this.mouseFrustum.intersectObjects(this.objects),
|
|
};
|
|
}
|
|
|
|
public setSelection(faceIds: Id[]) {
|
|
if (!this.meshes)
|
|
throw new Error('SceneHelper is not initiallized');
|
|
|
|
this.meshes.selection = faceIds;
|
|
}
|
|
|
|
public get objects(): Object3D[] {
|
|
if (!this.meshes)
|
|
throw new Error('SceneHelper is not initiallized');
|
|
|
|
return this.meshes.meshes;
|
|
}
|
|
|
|
public updateMouseFrustumHint() {
|
|
if (!this.camera)
|
|
throw new Error('SceneHelper is not initiallized');
|
|
|
|
this.hints.showFrustum('mouse', this.mouseFrustum.frustum);
|
|
}
|
|
|
|
public dispose() {
|
|
this.meshes?.dispose();
|
|
this.hints.clear();
|
|
}
|
|
|
|
public applyCamera() {
|
|
this._hints?.applyCamera();
|
|
}
|
|
}
|