Skip to content

Commit

Permalink
feat: refactor highlighter
Browse files Browse the repository at this point in the history
  • Loading branch information
xiangechen committed Jul 17, 2024
1 parent da8ea7a commit f889cb4
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 60 deletions.
4 changes: 3 additions & 1 deletion packages/chili-core/src/visual/highlighter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license.

import { ShapeType } from "../shape";
import { ShapeMeshData, ShapeType } from "../shape";
import { IVisualGeometry, VisualState } from "./visualShape";

export interface IHighlighter {
Expand All @@ -9,4 +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;
}
60 changes: 60 additions & 0 deletions packages/chili-three/src/threeGeometryFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license.

import {
AlwaysDepth,
BufferGeometry,
DoubleSide,
Float32BufferAttribute,
LineBasicMaterial,
LineDashedMaterial,
LineSegments,
Mesh,
MeshLambertMaterial,
Points,
PointsMaterial,
} from "three";
import { EdgeMeshData, FaceMeshData, LineType, VertexMeshData } from "chili-core";

export class ThreeGeometryFactory {
static createVertexGeometry(data: VertexMeshData) {
let buff = new BufferGeometry();
buff.setAttribute("position", new Float32BufferAttribute(data.positions, 3));
let color = data.color as number;
let material = new PointsMaterial({
size: data.size,
sizeAttenuation: false,
color,
});
material.depthFunc = AlwaysDepth;
return new Points(buff, material);
}

static createFaceGeometry(data: FaceMeshData) {
let buff = new BufferGeometry();
buff.setAttribute("position", new Float32BufferAttribute(data.positions, 3));
buff.setAttribute("normal", new Float32BufferAttribute(data.normals, 3));
buff.setAttribute("uv", new Float32BufferAttribute(data.uvs, 2));
buff.setIndex(data.indices);
buff.computeBoundingBox();
let material = new MeshLambertMaterial({ side: DoubleSide });
if (typeof data.color === "number") {
material.color.set(data.color);
} else {
material.vertexColors = true;
buff.setAttribute("color", new Float32BufferAttribute(data.color, 3));
}

return new Mesh(buff, material);
}

static createEdgeGeometry(data: EdgeMeshData) {
let buff = new BufferGeometry();
buff.setAttribute("position", new Float32BufferAttribute(data.positions, 3));
let color = data.color as number;
let material: LineBasicMaterial =
data.lineType === LineType.Dash
? new LineDashedMaterial({ color, dashSize: 6, gapSize: 6 })
: new LineBasicMaterial({ color });
return new LineSegments(buff, material).computeLineDistances();
}
}
49 changes: 48 additions & 1 deletion packages/chili-three/src/threeHighlighter.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
// Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license.

import { IHighlighter, IVisualGeometry, ShapeType, VisualConfig, VisualState } from "chili-core";
import {
IDisposable,
IHighlighter,
IVisualGeometry,
ShapeMeshData,
ShapeType,
VisualConfig,
VisualState,
} from "chili-core";
import {
DoubleSide,
Group,
LineBasicMaterial,
LineSegments,
Mesh,
MeshBasicMaterial,
MeshLambertMaterial,
Object3D,
Points,
Scene,
} from "three";
import { ThreeGeometry } from "./threeGeometry";
import { ThreeHelper } from "./threeHelper";
import { ThreeGeometryFactory } from "./threeGeometryFactory";

const hilightEdgeMaterial = new LineBasicMaterial({
color: ThreeHelper.fromColor(VisualConfig.highlightEdgeColor),
Expand Down Expand Up @@ -211,9 +222,14 @@ export class GeometryState {
export class ThreeHighlighter implements IHighlighter {
private readonly _stateMap = new Map<IVisualGeometry, GeometryState>();

readonly tempShapes: Group = new Group();
readonly sceneHorver: Scene = new Scene();
readonly sceneSelected: Scene = new Scene();

constructor() {
this.sceneHorver.add(this.tempShapes);
}

clear(): void {
this._stateMap.forEach((v, k) => {
this.resetState(k);
Expand Down Expand Up @@ -253,4 +269,35 @@ export class ThreeHighlighter implements IHighlighter {
}
return geometryState;
}

highliteMesh(...datas: ShapeMeshData[]): number {
let group = new Group();
datas.forEach((data) => {
if (ShapeMeshData.isVertex(data)) {
group.add(ThreeGeometryFactory.createVertexGeometry(data));
} else if (ShapeMeshData.isEdge(data)) {
group.add(ThreeGeometryFactory.createEdgeGeometry(data));
} else if (ShapeMeshData.isFace(data)) {
group.add(ThreeGeometryFactory.createFaceGeometry(data));
}
});
this.tempShapes.add(group);
return group.id;
}

removeMesh(id: number) {
let shape = this.tempShapes.getObjectById(id);
if (shape === undefined) return;
shape.children.forEach((x) => {
if (x instanceof Mesh || x instanceof LineSegments || x instanceof Points) {
x.geometry.dispose();
x.material.dispose();
}
if (IDisposable.isDisposable(x)) {
x.dispose();
}
});
shape.children.length = 0;
this.tempShapes.remove(shape);
}
}
60 changes: 4 additions & 56 deletions packages/chili-three/src/threeVisualContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import {
CollectionAction,
CollectionChangedArgs,
EdgeMeshData,
FaceMeshData,
IDisposable,
IModel,
INode,
Expand All @@ -13,37 +11,29 @@ import {
IVisualContext,
IVisualGeometry,
IVisualObject,
LineType,
Material,
MathUtils,
NodeAction,
NodeRecord,
ShapeMeshData,
ShapeType,
VertexMeshData,
XYZ,
} from "chili-core";
import {
AlwaysDepth,
Box3,
BufferGeometry,
DoubleSide,
Float32BufferAttribute,
Group,
LineBasicMaterial,
LineDashedMaterial,
LineSegments,
Mesh,
MeshLambertMaterial,
Object3D,
Points,
PointsMaterial,
RepeatWrapping,
Scene,
TextureLoader,
MeshLambertMaterial as ThreeMaterial,
} from "three";
import { ThreeGeometry } from "./threeGeometry";
import { ThreeGeometryFactory } from "./threeGeometryFactory";
import { ThreeHelper } from "./threeHelper";

export class ThreeVisualContext implements IVisualContext {
Expand Down Expand Up @@ -236,59 +226,17 @@ export class ThreeVisualContext implements IVisualContext {
let group = new Group();
datas.forEach((data) => {
if (ShapeMeshData.isVertex(data)) {
group.add(this.createVertexGeometry(data));
group.add(ThreeGeometryFactory.createVertexGeometry(data));
} else if (ShapeMeshData.isEdge(data)) {
group.add(this.createEdgeGeometry(data));
group.add(ThreeGeometryFactory.createEdgeGeometry(data));
} else if (ShapeMeshData.isFace(data)) {
group.add(this.createFaceGeometry(data));
group.add(ThreeGeometryFactory.createFaceGeometry(data));
}
});
this.tempShapes.add(group);
return group.id;
}

private createFaceGeometry(data: FaceMeshData) {
let buff = new BufferGeometry();
buff.setAttribute("position", new Float32BufferAttribute(data.positions, 3));
buff.setAttribute("normal", new Float32BufferAttribute(data.normals, 3));
buff.setAttribute("uv", new Float32BufferAttribute(data.uvs, 2));
buff.setIndex(data.indices);
buff.computeBoundingBox();
let material = new MeshLambertMaterial({ side: DoubleSide });
if (typeof data.color === "number") {
material.color.set(data.color);
} else {
material.vertexColors = true;
buff.setAttribute("color", new Float32BufferAttribute(data.color, 3));
}

return new Mesh(buff, material);
}

private createEdgeGeometry(data: EdgeMeshData) {
let buff = new BufferGeometry();
buff.setAttribute("position", new Float32BufferAttribute(data.positions, 3));
let color = data.color as number;
let material: LineBasicMaterial =
data.lineType === LineType.Dash
? new LineDashedMaterial({ color, dashSize: 6, gapSize: 6 })
: new LineBasicMaterial({ color });
return new LineSegments(buff, material).computeLineDistances();
}

private createVertexGeometry(data: VertexMeshData) {
let buff = new BufferGeometry();
buff.setAttribute("position", new Float32BufferAttribute(data.positions, 3));
let color = data.color as number;
let material = new PointsMaterial({
size: data.size,
sizeAttenuation: false,
color,
});
material.depthFunc = AlwaysDepth;
return new Points(buff, material);
}

removeMesh(id: number) {
let shape = this.tempShapes.getObjectById(id);
if (shape === undefined) return;
Expand Down
4 changes: 2 additions & 2 deletions packages/chili/src/commands/modify/trim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export class PickTrimEdgeEventHandler extends SelectionHandler {
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.context.displayMesh(mesh);
this.highlightedEdge = view.document.visual.highlighter.highliteMesh(mesh);
this.highlight = {
edge: detecteds[0],
segments,
Expand All @@ -126,7 +126,7 @@ export class PickTrimEdgeEventHandler extends SelectionHandler {

protected override cleanHighlights(): void {
if (this.highlightedEdge !== undefined) {
this.document.visual.context.removeMesh(this.highlightedEdge);
this.document.visual.highlighter.removeMesh(this.highlightedEdge);
this.highlightedEdge = undefined;
this.highlight = undefined;
this.document.application.activeView?.update();
Expand Down

0 comments on commit f889cb4

Please sign in to comment.