From 00ea42a090438830ebd017a19111dee148956467 Mon Sep 17 00:00:00 2001 From: xiange Date: Wed, 31 Jul 2024 20:14:01 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=A6=84=20refactor:=20LineSegments=20is=20?= =?UTF-8?q?changed=20to=20LineSegments2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/chili-core/src/config.ts | 8 +- packages/chili-core/src/shape/meshData.ts | 1 + packages/chili-core/src/visual/highlighter.ts | 4 +- packages/chili-geo/src/mesh.ts | 44 ++++- packages/chili-three/src/common.ts | 37 ++++ packages/chili-three/src/constants.ts | 2 +- packages/chili-three/src/threeGeometry.ts | 62 +++--- .../chili-three/src/threeGeometryFactory.ts | 38 +++- packages/chili-three/src/threeHighlighter.ts | 184 ++++++------------ packages/chili-three/src/threeView.ts | 59 +++--- packages/chili-three/src/threeVisual.ts | 2 +- .../chili-three/src/threeVisualContext.ts | 3 - packages/chili-three/test/testView.ts | 6 +- packages/chili-three/test/three.test.ts | 2 - .../chili-vis/src/selectionEventHandler.ts | 3 + packages/chili/src/commands/modify/trim.ts | 8 +- packages/chili/src/snap/snaps/axisSnap.ts | 2 +- 17 files changed, 238 insertions(+), 227 deletions(-) create mode 100644 packages/chili-three/src/common.ts diff --git a/packages/chili-core/src/config.ts b/packages/chili-core/src/config.ts index 2c4e31ab..7f1decdf 100644 --- a/packages/chili-core/src/config.ts +++ b/packages/chili-core/src/config.ts @@ -6,10 +6,10 @@ import { ObjectSnapType } from "./snapType"; export const VisualConfig = { defaultEdgeColor: 0x111111, defaultFaceColor: 0xdedede, - highlightEdgeColor: 0x0000ee, - highlightFaceColor: 0x0000ee, - selectedEdgeColor: 0x2222ff, - selectedFaceColor: 0x2222ff, + highlightEdgeColor: 0x4444cc, + highlightFaceColor: 0x4444cc, + selectedEdgeColor: 0x0000ff, + selectedFaceColor: 0x0000ff, editVertexSize: 7, editVertexColor: 0x0000ff, hintVertexSize: 5, diff --git a/packages/chili-core/src/shape/meshData.ts b/packages/chili-core/src/shape/meshData.ts index 34ba8c80..1504ec1e 100644 --- a/packages/chili-core/src/shape/meshData.ts +++ b/packages/chili-core/src/shape/meshData.ts @@ -55,6 +55,7 @@ export namespace VertexMeshData { export interface EdgeMeshData extends ShapeMeshData { lineType: LineType; + lineWidth?: number; } export namespace EdgeMeshData { diff --git a/packages/chili-core/src/visual/highlighter.ts b/packages/chili-core/src/visual/highlighter.ts index 6aff5f5c..4e536bc2 100644 --- a/packages/chili-core/src/visual/highlighter.ts +++ b/packages/chili-core/src/visual/highlighter.ts @@ -9,6 +9,6 @@ export interface IHighlighter { resetState(shape: IVisualGeometry): void; addState(shape: IVisualGeometry, state: VisualState, type: ShapeType, ...index: number[]): void; removeState(shape: IVisualGeometry, state: VisualState, type: ShapeType, ...index: number[]): void; - highliteMesh(...datas: ShapeMeshData[]): number; - removeMesh(id: number): void; + highlightMesh(...datas: ShapeMeshData[]): number; + removeHighlightMesh(id: number): void; } diff --git a/packages/chili-geo/src/mesh.ts b/packages/chili-geo/src/mesh.ts index b34253b6..a1ec782d 100644 --- a/packages/chili-geo/src/mesh.ts +++ b/packages/chili-geo/src/mesh.ts @@ -22,13 +22,49 @@ export class MeshUtils { }; } + static subFaceOutlines(face: FaceMeshData, index: number) { + let mesh = this.subFace(face, index); + if (!mesh) return undefined; + + return this.faceOutline(mesh); + } + + static faceOutline(face: { positions: number[]; indices: number[] }) { + let pointsMap = new Map(); + + const addEdge = (i: number, j: number) => { + let key = i < j ? `${i}_${j}` : `${j}_${i}`; + if (pointsMap.has(key)) { + pointsMap.get(key)!.count++; + return; + } + + const points = [ + ...face.positions.slice(i * 3, i * 3 + 3), + ...face.positions.slice(j * 3, j * 3 + 3), + ]; + pointsMap.set(key, { count: 1, points }); + }; + + for (let i = 0; i < face.indices.length; i += 3) { + addEdge(face.indices[i], face.indices[i + 1]); + addEdge(face.indices[i + 1], face.indices[i + 2]); + addEdge(face.indices[i + 2], face.indices[i]); + } + + let points: number[] = []; + pointsMap.forEach((v) => { + if (v.count === 1) { + points.push(...v.points); + } + }); + return points; + } + static subEdge(mesh: EdgeMeshData, index: number) { let group = mesh?.groups[index]; if (!group) return undefined; - let positions = mesh.positions.slice(group.start * 3, (group.start + group.count) * 3); - return { - positions, - }; + return mesh.positions.slice(group.start * 3, (group.start + group.count) * 3); } } diff --git a/packages/chili-three/src/common.ts b/packages/chili-three/src/common.ts new file mode 100644 index 00000000..a20f6441 --- /dev/null +++ b/packages/chili-three/src/common.ts @@ -0,0 +1,37 @@ +// Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. + +import { LineMaterial } from "three/examples/jsm/lines/LineMaterial"; +import { ThreeHelper } from "./threeHelper"; +import { VisualConfig } from "chili-core"; +import { DoubleSide } from "three"; + +export const hilightEdgeMaterial = new LineMaterial({ + linewidth: 2, + color: ThreeHelper.fromColor(VisualConfig.highlightEdgeColor), + side: DoubleSide, + polygonOffset: true, + polygonOffsetFactor: -4, + polygonOffsetUnits: -4, +}); + +export const hilightDashedEdgeMaterial = new LineMaterial({ + linewidth: 2, + color: ThreeHelper.fromColor(VisualConfig.highlightEdgeColor), + side: DoubleSide, + polygonOffset: true, + polygonOffsetFactor: -4, + polygonOffsetUnits: -4, + dashed: true, + dashScale: 100, + dashSize: 100, + gapSize: 100, +}); + +export const selectedEdgeMaterial = new LineMaterial({ + linewidth: 2, + color: ThreeHelper.fromColor(VisualConfig.selectedEdgeColor), + side: DoubleSide, + polygonOffset: true, + polygonOffsetFactor: -4, + polygonOffsetUnits: -4, +}); diff --git a/packages/chili-three/src/constants.ts b/packages/chili-three/src/constants.ts index e79a4410..362533cc 100644 --- a/packages/chili-three/src/constants.ts +++ b/packages/chili-three/src/constants.ts @@ -1,5 +1,5 @@ // Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. export class Constants { - static readonly RaycasterThreshold = 20; + static readonly RaycasterThreshold = 10; } diff --git a/packages/chili-three/src/threeGeometry.ts b/packages/chili-three/src/threeGeometry.ts index d777eca9..4ae746aa 100644 --- a/packages/chili-three/src/threeGeometry.ts +++ b/packages/chili-three/src/threeGeometry.ts @@ -6,32 +6,36 @@ import { GeometryEntity, IVisualGeometry, Matrix4, - ShapeMeshData, VisualConfig, } from "chili-core"; import { BufferGeometry, + DoubleSide, Float32BufferAttribute, - LineBasicMaterial, - LineSegments, Material, Mesh, MeshLambertMaterial, Object3D, - Color as ThreeColor, } from "three"; import { MeshUtils } from "chili-geo"; +import { LineMaterial } from "three/examples/jsm/lines/LineMaterial"; +import { LineSegments2 } from "three/examples/jsm/lines/LineSegments2"; +import { LineSegmentsGeometry } from "three/examples/jsm/lines/LineSegmentsGeometry"; import { ThreeHelper } from "./threeHelper"; import { ThreeVisualContext } from "./threeVisualContext"; export class ThreeGeometry extends Object3D implements IVisualGeometry { private _faceMaterial: Material; - private _edgeMaterial = new LineBasicMaterial({ - linewidth: 2, + private _edgeMaterial = new LineMaterial({ + linewidth: 1, color: VisualConfig.defaultEdgeColor, + side: DoubleSide, + polygonOffset: true, + polygonOffsetFactor: -2, + polygonOffsetUnits: -2, }); - private _edges?: LineSegments; + private _edges?: LineSegments2; private _faces?: Mesh; getMainMaterial() { @@ -94,8 +98,8 @@ export class ThreeGeometry extends Object3D implements IVisualGeometry { private generateShape() { let mesh = this.geometryEngity.shape.value?.mesh; - if (mesh?.faces?.positions.length) this.add(this.initFaces(mesh.faces)); - if (mesh?.edges?.positions.length) this.add(this.initEdges(mesh.edges)); + if (mesh?.faces?.positions.length) this.initFaces(mesh.faces); + if (mesh?.edges?.positions.length) this.initEdges(mesh.edges); } dispose() { @@ -118,12 +122,12 @@ export class ThreeGeometry extends Object3D implements IVisualGeometry { } private initEdges(data: EdgeMeshData) { - let buff = new BufferGeometry(); - buff.setAttribute("position", new Float32BufferAttribute(data.positions, 3)); - this.initColor(data, buff, this._edgeMaterial); + let buff = new LineSegmentsGeometry(); + buff.setPositions(data.positions); buff.computeBoundingBox(); - this._edges = new LineSegments(buff, this._edgeMaterial); - return this._edges; + + this._edges = new LineSegments2(buff, this._edgeMaterial); + this.add(this._edges); } private initFaces(data: FaceMeshData) { @@ -132,23 +136,10 @@ export class ThreeGeometry extends Object3D implements IVisualGeometry { buff.setAttribute("normal", new Float32BufferAttribute(data.normals, 3)); buff.setAttribute("uv", new Float32BufferAttribute(data.uvs, 2)); buff.setIndex(data.indices); - // this.initColor(data, buff, this._faceMaterial); buff.computeBoundingBox(); - this._faces = new Mesh(buff, this._faceMaterial); - return this._faces; - } - private initColor( - meshData: ShapeMeshData, - geometry: BufferGeometry, - material: LineBasicMaterial | MeshLambertMaterial, - ) { - if (meshData.color instanceof Array) { - material.vertexColors = true; - geometry.setAttribute("color", new Float32BufferAttribute(meshData.color, 3)); - } else { - material.color = new ThreeColor(meshData.color); - } + this._faces = new Mesh(buff, this._faceMaterial); + this.add(this._faces); } setFacesMateiralTemperary(material: MeshLambertMaterial) { @@ -157,7 +148,7 @@ export class ThreeGeometry extends Object3D implements IVisualGeometry { } } - setEdgesMateiralTemperary(material: LineBasicMaterial) { + setEdgesMateiralTemperary(material: LineMaterial) { if (this._edges) { this._edges.material = material; } @@ -169,14 +160,14 @@ export class ThreeGeometry extends Object3D implements IVisualGeometry { } cloneSubEdge(index: number) { - let mesh = MeshUtils.subEdge(this.geometryEngity.shape.value!.mesh.edges!, index); - if (!mesh) return undefined; + let positions = MeshUtils.subEdge(this.geometryEngity.shape.value!.mesh.edges!, index); + if (!positions) return undefined; - let buff = new BufferGeometry(); - buff.setAttribute("position", new Float32BufferAttribute(mesh.positions, 3)); + let buff = new LineSegmentsGeometry(); + buff.setPositions(positions); buff.applyMatrix4(this.matrixWorld); - return new LineSegments(buff, this._edgeMaterial); + return new LineSegments2(buff, this._edgeMaterial); } cloneSubFace(index: number) { @@ -188,6 +179,7 @@ export class ThreeGeometry extends Object3D implements IVisualGeometry { buff.setAttribute("normal", new Float32BufferAttribute(mesh.normals, 3)); buff.setIndex(mesh.indices); buff.applyMatrix4(this.matrixWorld); + return new Mesh(buff, this._faceMaterial); } diff --git a/packages/chili-three/src/threeGeometryFactory.ts b/packages/chili-three/src/threeGeometryFactory.ts index ce14480a..7c6594f3 100644 --- a/packages/chili-three/src/threeGeometryFactory.ts +++ b/packages/chili-three/src/threeGeometryFactory.ts @@ -1,19 +1,19 @@ // Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. +import { EdgeMeshData, FaceMeshData, LineType, VertexMeshData } from "chili-core"; import { AlwaysDepth, BufferGeometry, DoubleSide, Float32BufferAttribute, - LineBasicMaterial, - LineDashedMaterial, - LineSegments, Mesh, MeshLambertMaterial, Points, PointsMaterial, } from "three"; -import { EdgeMeshData, FaceMeshData, LineType, VertexMeshData } from "chili-core"; +import { LineMaterial } from "three/examples/jsm/lines/LineMaterial"; +import { LineSegments2 } from "three/examples/jsm/lines/LineSegments2"; +import { LineSegmentsGeometry } from "three/examples/jsm/lines/LineSegmentsGeometry"; export class ThreeGeometryFactory { static createVertexGeometry(data: VertexMeshData) { @@ -48,13 +48,31 @@ export class ThreeGeometryFactory { } static createEdgeGeometry(data: EdgeMeshData) { - let buff = new BufferGeometry(); - buff.setAttribute("position", new Float32BufferAttribute(data.positions, 3)); + let buff = new LineSegmentsGeometry(); + buff.setPositions(data.positions); + let color = data.color as number; - let material: LineBasicMaterial = + let linewidth = data.lineWidth ?? 1; + let material = data.lineType === LineType.Dash - ? new LineDashedMaterial({ color, dashSize: 6, gapSize: 6 }) - : new LineBasicMaterial({ color }); - return new LineSegments(buff, material).computeLineDistances(); + ? new LineMaterial({ + color, + dashed: true, + dashScale: 100, + dashSize: 100, + gapSize: 100, + linewidth, + polygonOffset: true, + polygonOffsetFactor: -4, + polygonOffsetUnits: -4, + }) + : new LineMaterial({ + color, + linewidth, + polygonOffset: true, + polygonOffsetFactor: -4, + polygonOffsetUnits: -4, + }); + return new LineSegments2(buff, material).computeLineDistances(); } } diff --git a/packages/chili-three/src/threeHighlighter.ts b/packages/chili-three/src/threeHighlighter.ts index 8275feae..57cca58c 100644 --- a/packages/chili-three/src/threeHighlighter.ts +++ b/packages/chili-three/src/threeHighlighter.ts @@ -6,49 +6,19 @@ import { IVisualGeometry, ShapeMeshData, ShapeType, - VisualConfig, VisualState, } from "chili-core"; -import { - DoubleSide, - Group, - LineBasicMaterial, - LineSegments, - Mesh, - MeshBasicMaterial, - MeshLambertMaterial, - Object3D, - Points, - Scene, -} from "three"; +import { MeshUtils } from "chili-geo"; +import { Group, Mesh, Points } from "three"; +import { LineSegments2 } from "three/examples/jsm/lines/LineSegments2"; +import { LineSegmentsGeometry } from "three/examples/jsm/lines/LineSegmentsGeometry"; +import { hilightEdgeMaterial, selectedEdgeMaterial } from "./common"; import { ThreeGeometry } from "./threeGeometry"; -import { ThreeHelper } from "./threeHelper"; import { ThreeGeometryFactory } from "./threeGeometryFactory"; - -const hilightEdgeMaterial = new LineBasicMaterial({ - color: ThreeHelper.fromColor(VisualConfig.highlightEdgeColor), -}); - -const selectedEdgeMaterial = new LineBasicMaterial({ - color: ThreeHelper.fromColor(VisualConfig.selectedEdgeColor), -}); - -const highlightFaceMaterial = new MeshLambertMaterial({ - color: ThreeHelper.fromColor(VisualConfig.highlightFaceColor), - side: DoubleSide, - transparent: true, - opacity: 0.85, -}); - -const selectedFaceMaterial = new MeshLambertMaterial({ - color: ThreeHelper.fromColor(VisualConfig.selectedFaceColor), - side: DoubleSide, - transparent: true, - opacity: 0.32, -}); +import { ThreeVisualContext } from "./threeVisualContext"; export class GeometryState { - private readonly _states: Map = new Map(); + private readonly _states: Map = new Map(); constructor( readonly highlighter: ThreeHighlighter, @@ -111,32 +81,11 @@ export class GeometryState { this._states.set(key, [newState, this.geometry as any]); } - private addSceneItem(scene: Scene, items: Object3D[]) { - let itemsToAdd = items.filter((x) => !scene.children.includes(x)); - scene.children.push(...itemsToAdd); - } - - private removeSceneItem(scene: Scene, items: Object3D[]) { - scene.children = scene.children.filter((x) => !items.includes(x)); - } - resetState() { - let hovers: (LineSegments | Mesh)[] = []; - let selected: (LineSegments | Mesh)[] = []; - this._states.forEach((state, key) => { - if (VisualState.hasState(state[0], VisualState.highlighter)) { - hovers.push(state[1]); - } - if (VisualState.hasState(state[0], VisualState.selected)) { - selected.push(state[1]); - } + this.highlighter.container.children.forEach((x) => { + (x as any).geometry?.dispose(); }); - - this.removeSceneItem(this.highlighter.sceneHorver, hovers); - this.removeSceneItem(this.highlighter.sceneSelected, selected); - hovers.forEach((x) => x.geometry?.dispose()); - selected.forEach((x) => x.geometry?.dispose()); - + this.highlighter.container.clear(); this._states.clear(); } @@ -146,86 +95,67 @@ export class GeometryState { type: ShapeType, index: number[], ) { - let addToHover: Object3D[] = []; - let addToSelected: Object3D[] = []; - let removeFromHover: Object3D[] = []; - let removeFromSelected: Object3D[] = []; - + let shouldRemoved: string[] = []; index.forEach((i) => { let key = this.state_key(type, i); let [oldState, newState] = this.updateStates(key, method, state); - this.addStateToRemove(key, oldState, newState, removeFromHover, removeFromSelected); - this.addStateToAdd(type, newState, key, i, addToHover, addToSelected); + if (oldState !== undefined && newState === VisualState.normal) { + shouldRemoved.push(key); + } else { + let geometry = this.getOrCloneGeometry(type, key, i); + if (geometry) { + let material = VisualState.hasState(newState, VisualState.highlighter) + ? hilightEdgeMaterial + : selectedEdgeMaterial; + geometry.material = material; + this._states.set(key, [newState, geometry]); + } + } }); - this.removeSceneItem(this.highlighter.sceneHorver, removeFromHover); - this.removeSceneItem(this.highlighter.sceneSelected, removeFromSelected); - this.addSceneItem(this.highlighter.sceneHorver, addToHover); - this.addSceneItem(this.highlighter.sceneSelected, addToSelected); - } - - private addStateToRemove( - key: string, - oldState: VisualState | undefined, - newState: VisualState, - removeFromHover: Object3D[], - removeFromSelected: Object3D[], - ) { - let item = this._states.get(key)?.[1]; - if (!item) return; - - if (oldState !== undefined && !VisualState.hasState(newState, VisualState.highlighter)) { - removeFromHover.push(item); - } - if (oldState !== undefined && !VisualState.hasState(newState, VisualState.selected)) { - removeFromSelected.push(item); - } - if (newState === VisualState.normal) this._states.delete(key); - } - - private addStateToAdd( - type: ShapeType, - newState: VisualState, - key: string, - i: number, - addToHover: Object3D[], - addToSelected: Object3D[], - ) { - let item = this.getOrCloneGeometry(type, key, i); - if (!item) return; - if (VisualState.hasState(newState, VisualState.highlighter)) { - addToHover.push(item); - } - if (VisualState.hasState(newState, VisualState.selected)) { - addToSelected.push(item); - } - this._states.set(key, [newState, item]); + shouldRemoved.forEach((key) => { + let item = this._states.get(key)?.[1]; + if (item) { + this.highlighter.container.remove(item); + item.geometry?.dispose(); + this._states.delete(key); + } + }); } private getOrCloneGeometry(type: ShapeType, key: string, index: number) { let geometry = this._states.get(key)?.[1]; if (geometry !== undefined) return geometry; + + let points: number[] | undefined = undefined; if (ShapeType.hasFace(type) || ShapeType.hasShell(type)) { - return this.geometry.cloneSubFace(index); + points = MeshUtils.subFaceOutlines(this.geometry.geometryEngity.shape.value!.mesh.faces!, index); } - if (ShapeType.hasEdge(type) || ShapeType.hasWire(type)) { - return this.geometry.cloneSubEdge(index); + if (points === undefined && (ShapeType.hasEdge(type) || ShapeType.hasWire(type))) { + points = MeshUtils.subEdge(this.geometry.geometryEngity.shape.value!.mesh.edges!, index); } - console.warn(`Invalid type ${type} for ${key}`); - return undefined; + if (!points) { + console.warn(`Invalid type ${type} for ${key}`); + return undefined; + } + + let lineGeometry = new LineSegmentsGeometry(); + lineGeometry.setPositions(points); + let segment = new LineSegments2(lineGeometry); + this.highlighter.container.add(segment); + return segment; } } export class ThreeHighlighter implements IHighlighter { private readonly _stateMap = new Map(); + readonly container: Group; - readonly tempShapes: Group = new Group(); - readonly sceneHorver: Scene = new Scene(); - readonly sceneSelected: Scene = new Scene(); - - constructor() { - this.sceneHorver.add(this.tempShapes); + constructor(readonly content: ThreeVisualContext) { + this.container = new Group(); + this.container.name = "highlighter"; + this.content.scene.add(this.container); } clear(): void { @@ -268,7 +198,7 @@ export class ThreeHighlighter implements IHighlighter { return geometryState; } - highliteMesh(...datas: ShapeMeshData[]): number { + highlightMesh(...datas: ShapeMeshData[]): number { let group = new Group(); datas.forEach((data) => { if (ShapeMeshData.isVertex(data)) { @@ -279,15 +209,15 @@ export class ThreeHighlighter implements IHighlighter { group.add(ThreeGeometryFactory.createFaceGeometry(data)); } }); - this.tempShapes.add(group); + this.container.add(group); return group.id; } - removeMesh(id: number) { - let shape = this.tempShapes.getObjectById(id); + removeHighlightMesh(id: number) { + let shape = this.container.getObjectById(id); if (shape === undefined) return; shape.children.forEach((x) => { - if (x instanceof Mesh || x instanceof LineSegments || x instanceof Points) { + if (x instanceof Mesh || x instanceof LineSegments2 || x instanceof Points) { x.geometry.dispose(); x.material.dispose(); } @@ -296,6 +226,6 @@ export class ThreeHighlighter implements IHighlighter { } }); shape.children.length = 0; - this.tempShapes.remove(shape); + this.container.remove(shape); } } diff --git a/packages/chili-three/src/threeView.ts b/packages/chili-three/src/threeView.ts index 83af7ab8..5378ab3e 100644 --- a/packages/chili-three/src/threeView.ts +++ b/packages/chili-three/src/threeView.ts @@ -11,7 +11,6 @@ import { Ray, ShapeMeshGroup, ShapeType, - VisualConfig, VisualShapeData, XY, XYZ, @@ -20,7 +19,6 @@ import { import { DirectionalLight, Intersection, - LineSegments, Mesh, Object3D, OrthographicCamera, @@ -32,10 +30,9 @@ import { WebGLRenderer, } from "three"; import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox"; -import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer"; +import { LineSegments2 } from "three/examples/jsm/lines/LineSegments2"; import { CameraController } from "./cameraController"; import { Constants } from "./constants"; -import { ThreeRenderBuilder } from "./threeRenderBuilder"; import { ThreeGeometry } from "./threeGeometry"; import { ThreeHelper } from "./threeHelper"; import { ThreeHighlighter } from "./threeHighlighter"; @@ -48,7 +45,6 @@ export class ThreeView extends Observable implements IView { private _scene: Scene; private _renderer: WebGLRenderer; - private _composer: EffectComposer; private _workplane: Plane; private _needsUpdate: boolean = false; private readonly _gizmo: ViewGizmo; @@ -72,10 +68,6 @@ export class ThreeView extends Observable implements IView { return this.cameraController.camera; } - get composer(): EffectComposer { - return this._composer; - } - constructor( readonly document: IDocument, name: string, @@ -90,7 +82,7 @@ export class ThreeView extends Observable implements IView { let resizerObserverCallback = debounce(this._resizerObserverCallback, 100); this._resizeObserver = new ResizeObserver(resizerObserverCallback); this.cameraController = new CameraController(this); - [this._renderer, this._composer] = this.initRender(); + this._renderer = this.initRenderer(); this._scene.add(this.dynamicLight); this._gizmo = new ViewGizmo(this); this.animate(); @@ -129,12 +121,14 @@ export class ThreeView extends Observable implements IView { return this._renderer; } - protected initRender() { - return new ThreeRenderBuilder(this._scene, this.camera) - .addOutlinePass(this.highlighter.sceneHorver, VisualConfig.highlightEdgeColor, true) - .addOutlinePass(this.highlighter.sceneSelected, VisualConfig.selectedEdgeColor, true) - .addGammaCorrection() - .build(); + protected initRenderer() { + let renderer = new WebGLRenderer({ + antialias: false, + alpha: true, + }); + renderer.setPixelRatio(window.devicePixelRatio); + + return renderer; } setDom(element: HTMLElement) { @@ -178,7 +172,7 @@ export class ThreeView extends Observable implements IView { let dir = this.camera.position.clone().sub(this.cameraController.target); this.dynamicLight.position.copy(dir); - this._composer.render(); + this._renderer.render(this._scene, this.camera); this._gizmo?.update(); this._needsUpdate = false; @@ -192,7 +186,6 @@ export class ThreeView extends Observable implements IView { this.camera.updateProjectionMatrix(); } this._renderer.setSize(width, heigth); - this._composer.setSize(width, heigth); this.update(); } @@ -279,7 +272,7 @@ export class ThreeView extends Observable implements IView { detecteds: VisualShapeData[], cache: Set, shapeType: ShapeType, - obj: Mesh | LineSegments, + obj: Mesh | LineSegments2, shapeFilter?: IShapeFilter, ) { if (!(obj.parent instanceof ThreeGeometry) || !obj.parent.visible) return; @@ -302,7 +295,7 @@ export class ThreeView extends Observable implements IView { if ((shape.shapeType & shapeType) === 0) return; if (shapeFilter && !shapeFilter.allow(shape)) return; - let groups = obj instanceof Mesh ? shape.mesh.faces?.groups : shape.mesh.edges?.groups; + let groups = obj instanceof LineSegments2 ? shape.mesh.edges?.groups : shape.mesh.faces?.groups; addShape([...Array(groups?.length).keys()]); } @@ -316,17 +309,16 @@ export class ThreeView extends Observable implements IView { private detectThreeShapes(intersections: Intersection[], shapeFilter?: IShapeFilter): VisualShapeData[] { for (const element of intersections) { const parent = element.object.parent; - if ( - !(parent instanceof ThreeGeometry) || - (shapeFilter && !shapeFilter.allow(parent.geometryEngity.shape.value!)) - ) { + if (!(parent instanceof ThreeGeometry)) continue; + + if (shapeFilter && !shapeFilter.allow(parent.geometryEngity.shape.value!)) { continue; } return [ { owner: parent, shape: parent.geometryEngity.shape.value!, - point: ThreeHelper.toXYZ(element.point), + point: ThreeHelper.toXYZ(element.pointOnLine ?? element.point), indexes: [], }, ]; @@ -351,7 +343,7 @@ export class ThreeView extends Observable implements IView { owner: visualShape, shape: shape, directShape, - point: ThreeHelper.toXYZ(intersected.point), + point: ThreeHelper.toXYZ(intersected.pointOnLine ?? intersected.point), indexes, }); } @@ -415,16 +407,16 @@ export class ThreeView extends Observable implements IView { let shape: IShape | undefined = undefined; let index: number | undefined = undefined; let groups: ShapeMeshGroup[] | undefined = undefined; - if (element.index !== undefined) { + if (element.pointOnLine !== undefined) { groups = parent.geometryEngity.shape.value?.mesh.edges?.groups; if (groups) { - index = ThreeHelper.findGroupIndex(groups, element.index)!; + index = ThreeHelper.findGroupIndex(groups, element.faceIndex! * 2)!; shape = groups[index].shape; } - } else if (element.faceIndex !== undefined) { + } else { groups = parent.geometryEngity.shape.value?.mesh.faces?.groups; if (groups) { - index = ThreeHelper.findGroupIndex(groups, element.faceIndex * 3)!; + index = ThreeHelper.findGroupIndex(groups, element.faceIndex! * 3)!; shape = groups[index].shape; } } @@ -472,7 +464,12 @@ export class ThreeView extends Observable implements IView { let { x, y } = this.screenToCameraRect(mx, my); let mousePos = new Vector2(x, y); raycaster.setFromCamera(mousePos, this.camera); - raycaster.params = { ...raycaster.params, Line: { threshold }, Points: { threshold } }; + raycaster.params = { + ...raycaster.params, + Line2: { threshold }, + Line: { threshold }, + Points: { threshold }, + }; return raycaster; } } diff --git a/packages/chili-three/src/threeVisual.ts b/packages/chili-three/src/threeVisual.ts index 576b8b81..791cdf19 100644 --- a/packages/chili-three/src/threeVisual.ts +++ b/packages/chili-three/src/threeVisual.ts @@ -36,7 +36,7 @@ export class ThreeVisual implements IVisual { this.defaultEventHandler = new ModelSelectionHandler(document, true); this.context = new ThreeVisualContext(this, this.scene); this.viewHandler = new ThreeViewHandler(); - this.highlighter = new ThreeHighlighter(); + this.highlighter = new ThreeHighlighter(this.context); this.textGenerator = new ThreeTextGenerator(); this._eventHandler = this.defaultEventHandler; } diff --git a/packages/chili-three/src/threeVisualContext.ts b/packages/chili-three/src/threeVisualContext.ts index c28d372a..c12d7a92 100644 --- a/packages/chili-three/src/threeVisualContext.ts +++ b/packages/chili-three/src/threeVisualContext.ts @@ -63,9 +63,6 @@ export class ThreeVisualContext implements IVisualContext { side: DoubleSide, transparent: true, name: item.name, - polygonOffset: true, - polygonOffsetFactor: 1, - polygonOffsetUnits: 2, }); material.map = this.loadTexture(item); item.onPropertyChanged(this.onMaterialPropertyChanged); diff --git a/packages/chili-three/test/testView.ts b/packages/chili-three/test/testView.ts index f621a7c8..daf49aa6 100644 --- a/packages/chili-three/test/testView.ts +++ b/packages/chili-three/test/testView.ts @@ -61,7 +61,7 @@ Object.defineProperties(container, { export class TestView extends ThreeView { constructor(document: IDocument, content: ThreeVisualContext) { - super(document, "test", Plane.XY, new ThreeHighlighter(), content); + super(document, "test", Plane.XY, new ThreeHighlighter(content), content); this.setDom(container); this.cameraController.lookAt( new THREE.Vector3(0, 0, 1), @@ -70,10 +70,10 @@ export class TestView extends ThreeView { ); } - protected override initRender() { + protected override initRenderer() { let render = new TestWebGLRenderer() as any; render.setSize(container.clientWidth, container.clientHeight); container.appendChild(render.domElement); - return [render, render] as any; + return render; } } diff --git a/packages/chili-three/test/three.test.ts b/packages/chili-three/test/three.test.ts index eaf9136f..c55a34ce 100644 --- a/packages/chili-three/test/three.test.ts +++ b/packages/chili-three/test/three.test.ts @@ -6,8 +6,6 @@ import { TestDocument } from "./testDocument"; import { TestBody } from "./testEdge"; import { TestView } from "./testView"; -import { ThreeRenderBuilder } from "../src/threeRenderBuilder"; - jest.mock("../src/threeRenderBuilder", () => ({ ThreeRenderBuilder: jest.fn(), })); diff --git a/packages/chili-vis/src/selectionEventHandler.ts b/packages/chili-vis/src/selectionEventHandler.ts index 643a5ea3..9ddc6da2 100644 --- a/packages/chili-vis/src/selectionEventHandler.ts +++ b/packages/chili-vis/src/selectionEventHandler.ts @@ -53,6 +53,9 @@ export abstract class SelectionHandler implements IEventHandler { dispose() {} pointerMove(view: IView, event: PointerEvent): void { + if (event.buttons === 4) { + return; + } this._detectAtMouse = undefined; if (this.rect) { this.updateRect(this.rect, event); diff --git a/packages/chili/src/commands/modify/trim.ts b/packages/chili/src/commands/modify/trim.ts index 6b428704..14a01da1 100644 --- a/packages/chili/src/commands/modify/trim.ts +++ b/packages/chili/src/commands/modify/trim.ts @@ -15,6 +15,7 @@ import { IView, ShapeType, Transaction, + VisualConfig, VisualShapeData, command, } from "chili-core"; @@ -113,8 +114,9 @@ export class PickTrimEdgeEventHandler extends SelectionHandler { let curve = edge.curve(); let segments = findSegments(curve, edge, otherEdges, detecteds); let mesh = edge.trim(segments.deleteSegment.start, segments.deleteSegment.end).mesh.edges!; - mesh.color = 0xff0000; - this.highlightedEdge = view.document.visual.highlighter.highliteMesh(mesh); + mesh.color = VisualConfig.highlightEdgeColor; + mesh.lineWidth = 2; + this.highlightedEdge = view.document.visual.highlighter.highlightMesh(mesh); this.highlight = { edge: detecteds[0], segments, @@ -126,7 +128,7 @@ export class PickTrimEdgeEventHandler extends SelectionHandler { protected override cleanHighlights(): void { if (this.highlightedEdge !== undefined) { - this.document.visual.highlighter.removeMesh(this.highlightedEdge); + this.document.visual.highlighter.removeHighlightMesh(this.highlightedEdge); this.highlightedEdge = undefined; this.highlight = undefined; this.document.application.activeView?.update(); diff --git a/packages/chili/src/snap/snaps/axisSnap.ts b/packages/chili/src/snap/snaps/axisSnap.ts index 3940f67c..0033cb32 100644 --- a/packages/chili/src/snap/snaps/axisSnap.ts +++ b/packages/chili/src/snap/snaps/axisSnap.ts @@ -32,7 +32,7 @@ export class AxisSnap implements ISnap { } private showTempLine(view: IView, dot: number) { - let dist = Math.abs(dot) < 0.000001 ? 1e20 : 1e20 * dot; + let dist = Math.abs(dot) < 0.000001 ? 1e15 : 1e15 * dot; let lineDats = EdgeMeshData.from( this.point, this.point.add(this.direction.multiply(dist)),