diff --git a/client/src/components/Viewport.tsx b/client/src/components/Viewport.tsx index 6555c62..a393c16 100644 --- a/client/src/components/Viewport.tsx +++ b/client/src/components/Viewport.tsx @@ -1,5 +1,4 @@ import { useSceneHelper } from "../helpers/hooks/useSceneHelper"; -import { model } from "../model/model"; import { state } from "../state/root"; import { ThreeView, type ThreeViewEventArgs, type ThreeViewMouseEventArgs } from "./ThreeView"; diff --git a/client/src/helpers/circularFrustumIntersect.ts b/client/src/helpers/circularFrustumIntersect.ts index d79a9f2..78d4298 100644 --- a/client/src/helpers/circularFrustumIntersect.ts +++ b/client/src/helpers/circularFrustumIntersect.ts @@ -25,7 +25,7 @@ export type FaceHitResult = BaseHitResult & { export type EdgeHitResult = BaseHitResult & { kind: 'edge', - id?: Id, + id: Id, faceId: Id, } diff --git a/client/src/helpers/sceneHelper.ts b/client/src/helpers/sceneHelper.ts index 8586a36..fdf4eff 100644 --- a/client/src/helpers/sceneHelper.ts +++ b/client/src/helpers/sceneHelper.ts @@ -1,4 +1,4 @@ -import type { Object3D, OrthographicCamera, PerspectiveCamera, Scene, Vector2Like, WebGLRenderer } from "three"; +import { Mesh, MeshStandardMaterial, PlaneGeometry, type Object3D, type OrthographicCamera, type PerspectiveCamera, type Scene, type Vector2Like, type WebGLRenderer } from "three"; import { MeshCache } from "../layers/meshCache"; import { GeometryCache } from "../layers/geometryCache"; import type { Id } from "../types"; @@ -37,6 +37,15 @@ export class SceneHelper { for (const mesh of meshes) this.meshes.addMesh(mesh.faceId, mesh); } + + const plane = new Mesh( + new PlaneGeometry(14, 14), + new MeshStandardMaterial({ color: 0x080810 }), + ); + plane.rotation.x = -Math.PI / 2; + plane.receiveShadow = true; + + this.meshes.addRawMesh('xyplane', plane); } public get hints(): ThreeHintDisplay { @@ -84,7 +93,9 @@ export class SceneHelper { if (!this.meshes) throw new Error('SceneHelper is not initiallized'); - return this.meshes.meshes; + return [ + ...this.meshes.meshes, + ]; } public updateMouseFrustumHint() { diff --git a/client/src/layers/geometryCache.ts b/client/src/layers/geometryCache.ts index eed381b..0303fd3 100644 --- a/client/src/layers/geometryCache.ts +++ b/client/src/layers/geometryCache.ts @@ -4,24 +4,20 @@ import type { MeshDto } from '../backend/dto'; export class GeometryCache { private readonly items = new Map(); - private key(id: string, lod: number) { - return `${id}:${lod}`; + public has(id: string): boolean { + return this.items.has(id); } - public has(id: string, lod: number): boolean { - return this.items.has(this.key(id, lod)); + public get(id: string): THREE.BufferGeometry | undefined { + return this.items.get(id); } - public get(id: string, lod: number): THREE.BufferGeometry | undefined { - return this.items.get(this.key(id, lod)); + public set(id: string, payload: THREE.BufferGeometry) { + this.items.set(id, payload); } - public set(id: string, lod: number, payload: THREE.BufferGeometry) { - this.items.set(this.key(id, lod), payload); - } - - public getOrCreate(id: string, lod: number, dto: MeshDto): THREE.BufferGeometry { - let geometry = this.get(id, lod); + public createMesh(id: string, dto: MeshDto): THREE.BufferGeometry { + let geometry = this.get(id); if (geometry) return geometry; @@ -32,16 +28,16 @@ export class GeometryCache { geometry.setAttribute('normal', new THREE.BufferAttribute(dto.normals, 3)); geometry.setIndex(new THREE.BufferAttribute(dto.indices, 1)); - this.set(id, lod, geometry); + this.set(id, geometry); return geometry; } - unset(id: string, lod: number) { - const geometry = this.get(id, lod); + unset(id: string) { + const geometry = this.get(id); if (geometry) { geometry.dispose(); - this.items.delete(this.key(id, lod)); + this.items.delete(id); } } } \ No newline at end of file diff --git a/client/src/layers/meshCache.ts b/client/src/layers/meshCache.ts index b442f41..dcef460 100644 --- a/client/src/layers/meshCache.ts +++ b/client/src/layers/meshCache.ts @@ -67,19 +67,25 @@ export class MeshCache { return Object.values(this.items); } - // Called when FE scene graph syncs from BE - addMesh(id: string, dto: MeshDto) { + public addMesh(id: string, dto: MeshDto) { if (this.items[id]) return; - const geo = this.cache.getOrCreate(id, 0, dto); + const geometry = this.cache.createMesh(id, dto); + const mesh = new THREE.Mesh(geometry, this.baseMaterial); + + this.addRawMesh(id, mesh); - const geoVCount = geo.attributes.position.count; - geo.setAttribute('selected', new THREE.BufferAttribute(new Float32Array(geoVCount), 1)); - - const mesh = new THREE.Mesh(geo, this.baseMaterial); mesh.userData = dto mesh.userData.vertexIds = dto.loop.map((v) => v.vertex); + } + + public addRawMesh(id: string, mesh: THREE.Mesh) { + if (this.items[id]) + return; + + const geoVCount = mesh.geometry.attributes.position.count; + mesh.geometry.setAttribute('selected', new THREE.BufferAttribute(new Float32Array(geoVCount), 1)); this.scene.add(mesh); this.items[id] = mesh; @@ -111,7 +117,7 @@ export class MeshCache { else mesh.material.dispose(); - this.cache.unset((mesh.userData as MeshDto).faceId, 0); + this.cache.unset((mesh.userData as MeshDto).faceId); delete (this.items[id]); } diff --git a/client/src/verb/meshService.ts b/client/src/verb/meshService.ts index f10fd19..945be30 100644 --- a/client/src/verb/meshService.ts +++ b/client/src/verb/meshService.ts @@ -1,11 +1,7 @@ -import verb from "verb-nurbs"; - import type { Solid, Surface } from "../types/brep"; import { db } from "../backend/db"; import { NURBSBuilder } from "./NURBSBuilder"; -const verbAny = verb as any; - export type Point = [number, number, number]; export type Tri = [number, number, number]; export type UV = [number, number];