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