CAD/client/src/helpers/sceneHelper.ts

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