diff --git a/src/components/Model3DView.vue b/src/components/Model3DView.vue index 2eeeaa1..d2dfb79 100644 --- a/src/components/Model3DView.vue +++ b/src/components/Model3DView.vue @@ -176,6 +176,9 @@ watch(() => restate.mode, (newVal) => { } }) +/** + * 添加输送线 + */ function addConveyor() { const conveyorLength = 10 // 长度 const conveyorWidth = 0.8 // 宽度 @@ -1029,7 +1032,6 @@ function handleFileChange(file) { const arrayBuffer = reader.result //@ts-ignore loader.parseAsync(arrayBuffer, '').then((content) => { - debugger addGroupToScene(content.scene) }) diff --git a/src/core/Constract.ts b/src/core/Constract.ts index de837ab..800e6b0 100644 --- a/src/core/Constract.ts +++ b/src/core/Constract.ts @@ -33,8 +33,10 @@ const Constract = Object.freeze({ HEIGHT_WAY_LABEL: 0.03, HEIGHT_WAY_LINE: 0.02, + MAX_WAY_INSTANCES: 10000, + MAX_WAY_LINE_INSTANCES: 40000, MAX_MEASURE_INSTANCES: 1000, MAX_GSTORE_INSTANCES: 10000, - MAX_PALLET_INSTANCES: 10000, + MAX_PALLET_INSTANCES: 10000 }) export default Constract diff --git a/src/core/ModelUtils.ts b/src/core/ModelUtils.ts index 32b988e..14dfa6e 100644 --- a/src/core/ModelUtils.ts +++ b/src/core/ModelUtils.ts @@ -495,6 +495,27 @@ export async function loadByUrl(url): Promise { }) } +/** + * 通过两点位置生成一个平面矩阵, z轴为平面长度, x轴为平面宽度 + * @param startPosition + * @param endPosition + */ +export function linkPlaneByPoint(startPosition: THREE.Vector3, endPosition: THREE.Vector3, width: number): THREE.Matrix4 { + const dir = new THREE.Vector3().subVectors(endPosition, startPosition) + const length = dir.length() // 平面长度 = 两点距离 + dir.normalize() + + const center = new THREE.Vector3().addVectors(startPosition, endPosition).multiplyScalar(0.5) + // const orientation = new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 0, 1), dir) + + const dummy = new THREE.Object3D() + dummy.position.copy(center) + dummy.quaternion.setFromRotationMatrix(new THREE.Matrix4().lookAt(startPosition, endPosition, new THREE.Vector3(0, 1, 0))) + dummy.scale.set(width, 1, length) // Z轴缩放为长度 + dummy.updateMatrix() + return dummy.matrix +} + export async function loadGlbModule(url: string): Promise { const response = await axios.get(url, { responseType: 'arraybuffer' @@ -528,42 +549,3 @@ export function load3DModule(arrayBuffer: ArrayBuffer | string, ext: string) { return null } } - -export async function generateMaterialWithTexture(color: number, quality: number, info: any, textureInfos: any) { - let materialClone - - let url = color?.toString() + ' ' + JSON.stringify(textureInfos) + ' ' + quality + ' ' + (info == undefined ? '' : JSON.stringify(info)) - - if (!this.materialsWithTextureMap[url]) { - let meterialTmp = await this.generateMaterial(color, quality, info) - for (let textureInfo of textureInfos) { - if (textureInfo.path != undefined && textureInfo.repeatX != undefined && textureInfo.repeatY != undefined) { - let textureTmp = await this.generateTexture(textureInfo.path, textureInfo.repeatX, textureInfo.repeatY) - - if (textureInfo.rotation != undefined) { - textureTmp.rotation = textureInfo.rotation - } - if (textureInfo.normalMapType != undefined) { - textureTmp.normalMapType = textureInfo.normalMapType - } - - if (textureInfo.type == Model.TextureTypeEnum.NormalMap) { - if (quality != Model.MaterialQualityEnum.Low) { - meterialTmp.normalMap = textureTmp - } - } else if (textureInfo.type == Model.TextureTypeEnum.AlphaMap) { - meterialTmp.alphaMap = textureTmp - } else if (textureInfo.type == Model.TextureTypeEnum.Map) { - meterialTmp.map = textureTmp - } else { - meterialTmp.map = textureTmp - } - meterialTmp.needsUpdate = true - } - } - this.materialsWithTextureMap[url] = meterialTmp - } - materialClone = this.materialsWithTextureMap[url] - - return materialClone -} diff --git a/src/core/base/BaseRenderer.ts b/src/core/base/BaseRenderer.ts index f0e6786..301449c 100644 --- a/src/core/base/BaseRenderer.ts +++ b/src/core/base/BaseRenderer.ts @@ -1,6 +1,6 @@ import type Viewport from '@/core/engine/Viewport' import * as THREE from 'three' -import { getLineId, setUserDataForItem, setUserDataForLine } from '@/core/ModelUtils.ts' +import { getLineId, linkPlaneByPoint, setUserDataForItem, setUserDataForLine } from '@/core/ModelUtils.ts' import { Line2 } from 'three/examples/jsm/lines/Line2' import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts' import Constract from '@/core/Constract.ts' @@ -223,11 +223,25 @@ export default abstract class BaseRenderer { this.tempViewport.entityManager.appendLineObject(id, line) if (line instanceof THREE.Object3D) { this.appendToScene(line) + + } else if (line instanceof PointManageWrap) { + line.manager.syncMeshObject3D(line) } this.afterCreateOrUpdateLine(start, end, type, option, line) } + updateLineEntity(start: ItemJson, end: ItemJson, type: LinkType, option: any = {}) { + const lineId = getLineId(start.id, end.id, type) + const line = this.tempViewport.entityManager.findLineObjectById(lineId) + + option.lineId = lineId + option.line = line + + this.updateLine(start, end, type, option) + this.afterCreateOrUpdateLine(start, end, type, option, line) + } + /** * 更新一根线 * @param start 起点 @@ -235,10 +249,8 @@ export default abstract class BaseRenderer { * @param type 线的类型 * @param option 渲染选项 */ - updateLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) { - const lineId = getLineId(start.id, end.id, type) - - const line = this.tempViewport.entityManager.findLineObjectById(lineId) + updateLine(start: ItemJson, end: ItemJson, type: LinkType, option: any) { + const { line, lineId } = option const startPoint = this.tempViewport.entityManager.findObjectById(start.id) const endPoint = this.tempViewport.entityManager.findObjectById(end.id) @@ -249,8 +261,6 @@ export default abstract class BaseRenderer { } else if (line instanceof LineManageWrap) { line.manager.updateLine(lineId, startPoint.position, endPoint.position, line.color) } - - this.afterCreateOrUpdateLine(start, end, type, option, line) } /** diff --git a/src/core/manager/EntityManager.ts b/src/core/manager/EntityManager.ts index d4128c7..bb4a831 100644 --- a/src/core/manager/EntityManager.ts +++ b/src/core/manager/EntityManager.ts @@ -226,7 +226,7 @@ export default class EntityManager { // 只通知起点对应的渲染器 continue } - renderer.updateLine(start, end, lineDiffItem.type) + renderer.updateLineEntity(start, end, lineDiffItem.type) } // "线"删除 diff --git a/src/core/manager/InstancePointManager.ts b/src/core/manager/InstancePointManager.ts index 05effac..bc872b2 100644 --- a/src/core/manager/InstancePointManager.ts +++ b/src/core/manager/InstancePointManager.ts @@ -19,6 +19,19 @@ export default class InstancePointManager { // instanceId -> itemId private __indexIdMap = new Map() + createPointSimple(id: string): PointManageWrap { + //@ts-ignore + const wrap = this.createPoint({ + id: id, + name: id, + v: true, + tf: [[0, 0, 0], [0, 0, 0], [0, 0, 0]], + dt: {} + }) + + return wrap + } + /** * 创建点实例 * @param item 点数据 @@ -233,6 +246,18 @@ export class PointManageWrap { this.meshIndex = -1 } + applyMatrix4(matrix: THREE.Matrix4): void { + const position = new THREE.Vector3() + const quaternion = new THREE.Quaternion() + const scale = new THREE.Vector3() + matrix.decompose(position, quaternion, scale) + + this.position.copy(position) + this.rotation.setFromQuaternion(quaternion) + this.scale.copy(scale) + this.manager.syncMeshObject3D(this) + } + createBox3(): THREE.Box3 { const instancedMesh = this.manager.instancedMesh const matrix = new THREE.Matrix4() diff --git a/src/core/manager/LabelManager.ts b/src/core/manager/LabelManager.ts index cd5aa04..e2713dd 100644 --- a/src/core/manager/LabelManager.ts +++ b/src/core/manager/LabelManager.ts @@ -28,6 +28,8 @@ export interface LabelOption { */ padding?: number | string text?: string + + format?: (distance: number) => string } /** @@ -58,7 +60,10 @@ export default class LabelManager implements IControls { // 计算距离 const distance = startPos.distanceTo(endPos) - const text = distance.toFixed(2) + ' m' + let text = distance.toFixed(2) + ' m' + if (option.format) { + text = option.format(distance) + } this.updateLabel(lineRef, text) return labelObj diff --git a/src/core/manager/LineSegmentManager.ts b/src/core/manager/LineSegmentManager.ts index db7eb40..c17e740 100644 --- a/src/core/manager/LineSegmentManager.ts +++ b/src/core/manager/LineSegmentManager.ts @@ -4,13 +4,15 @@ import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeome import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2' import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' import type { Object3DLike, Vector3Like } from '@/types/ModelTypes.ts' +import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry' +import { Line2 } from 'three/examples/jsm/lines/Line2' /** * 线段管理器 */ export default class LineSegmentManager { private readonly viewport: Viewport - private readonly lineGeometry: LineSegmentsGeometry + private readonly lineGeometry: LineGeometry // LineSegmentsGeometry private readonly lineMaterial: LineMaterial private readonly lineSegments: LineSegments2 private readonly segments: Map = new Map() @@ -242,7 +244,7 @@ export default class LineSegmentManager { this.lineGeometry.setColors(this.colorArray) // 设置实例计数为可见线段数量 - this.lineGeometry.instanceCount = Array.from(this.segments.values()).filter(s => s.visible).length + // this.lineGeometry.instanceCount = Array.from(this.segments.values()).filter(s => s.visible).length this.needsUpdate = false } @@ -257,10 +259,10 @@ export default class LineSegmentManager { this.viewport = viewport this.lineMaterial = lineMaterial - this.lineGeometry = new LineSegmentsGeometry() + this.lineGeometry = new LineGeometry() // new LineSegmentsGeometry() // 创建线段的渲染对象 - this.lineSegments = new LineSegments2(this.lineGeometry, this.lineMaterial) + this.lineSegments = new Line2(this.lineGeometry, this.lineMaterial) this.lineSegments.name = name this.lineSegments.frustumCulled = false this.viewport.scene.add(this.lineSegments) diff --git a/src/example/ExampleUtil.js b/src/example/ExampleUtil.js index 7c61487..39c814d 100644 --- a/src/example/ExampleUtil.js +++ b/src/example/ExampleUtil.js @@ -68,17 +68,18 @@ export function buildAgvPerformanceData(t, rows, cols) { } } - data.get('wp_0_0').dt.center.push('wp_0_' + (cols - 1)) - data.get('wp_0_' + (cols - 1)).dt.center.push('wp_0_0') - - data.get('wp_' + (rows - 1) + '_0').dt.center.push('wp_' + (rows - 1) + '_' + (cols - 1)) - data.get('wp_' + (rows - 1) + '_' + (cols - 1)).dt.center.push('wp_' + (rows - 1) + '_0') - - data.get('wp_' + (rows - 1) + '_0').dt.center.push('wp_0_0') - data.get('wp_0_0').dt.center.push('wp_' + (rows - 1) + '_0') - - data.get('wp_' + (rows - 1) + '_' + (cols - 1)).dt.center.push('wp_0_' + (cols - 1)) - data.get('wp_0_' + (cols - 1)).dt.center.push('wp_' + (rows - 1) + '_' + (cols - 1)) + // 四个对角连线 + // data.get('wp_0_0').dt.center.push('wp_0_' + (cols - 1)) + // data.get('wp_0_' + (cols - 1)).dt.center.push('wp_0_0') + // + // data.get('wp_' + (rows - 1) + '_0').dt.center.push('wp_' + (rows - 1) + '_' + (cols - 1)) + // data.get('wp_' + (rows - 1) + '_' + (cols - 1)).dt.center.push('wp_' + (rows - 1) + '_0') + // + // data.get('wp_' + (rows - 1) + '_0').dt.center.push('wp_0_0') + // data.get('wp_0_0').dt.center.push('wp_' + (rows - 1) + '_0') + // + // data.get('wp_' + (rows - 1) + '_' + (cols - 1)).dt.center.push('wp_0_' + (cols - 1)) + // data.get('wp_0_' + (cols - 1)).dt.center.push('wp_' + (rows - 1) + '_' + (cols - 1)) return Array.from(data.values()) } diff --git a/src/example/example1.js b/src/example/example1.js index 91774a7..4a919ab 100644 --- a/src/example/example1.js +++ b/src/example/example1.js @@ -330,13 +330,27 @@ export default { t: 'carton', v: true, tf: [[0, 0.1, 0], [0, 0, 0], [1.0, 1.0, 1.0]], - dt: { in: [], out: [], center: [], storeWidth: 1.4, storeDepth: 1.4 } + dt: { in: [], out: [], center: [] } + }, + { + id: 'way1', + t: 'way', + v: true, + tf: [[2, 0.1, 0], [0, 0, 0], [1.0, 1.0, 1.0]], + dt: { in: [], out: [], center: ['way2'] } + }, + { + id: 'way2', + t: 'way', + v: true, + tf: [[5, 0.1, 0], [0, 0, 0], [1.0, 1.0, 1.0]], + dt: { in: [], out: [], center: ['way1'] } } ] }, { catalogCode: '__f1', t: 'floor', - items: buildAgvPerformanceData('measure', 100, 100) + items: buildAgvPerformanceData('way', 100, 100) }, { catalogCode: '__f2', t: 'floor', diff --git a/src/modules/carton/CartonRenderer.ts b/src/modules/carton/CartonRenderer.ts index c8c6dd8..80c53a2 100644 --- a/src/modules/carton/CartonRenderer.ts +++ b/src/modules/carton/CartonRenderer.ts @@ -37,11 +37,15 @@ export default class PalletRenderer extends BaseRenderer { this.cartonGeometry = mesh.geometry this.cartonMaterial = new THREE.MeshPhongMaterial({ color: 0xc29a70 }) // mesh.material as THREE.Material this.cartonGeometry.scale(0.01, 0.01, 0.01) - this.cartonGeometry.rotateX(Math.PI / 2) + // this.cartonGeometry.rotateX(-Math.PI / 2) + this.cartonGeometry.center() + this.cartonGeometry.translate(0, 0.3, 0) + cartonTexture.flipY = true cartonTexture.wrapS = THREE.RepeatWrapping cartonTexture.wrapT = THREE.RepeatWrapping - cartonTexture.repeat.set(1, 1) + cartonTexture.repeat.set(1, -1) + cartonTexture.offset.y = 1 //@ts-ignore this.cartonMaterial.map = cartonTexture //@ts-ignore diff --git a/src/modules/measure/MeasureRenderer.ts b/src/modules/measure/MeasureRenderer.ts index ebe4285..da57375 100644 --- a/src/modules/measure/MeasureRenderer.ts +++ b/src/modules/measure/MeasureRenderer.ts @@ -34,32 +34,6 @@ export default class MeasureRenderer extends BaseRenderer { readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.25, 0.25, 0.1) readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(90, 0, 0) - get pointManager(): InstancePointManager { - if (!this.tempViewport) { - throw new Error('tempViewport is not set.') - } - return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () => - // 构建 InstanceMesh 代理对象 - InstancePointManager.create(this.itemTypeName, - this.tempViewport, - this.pointGeometry, - this.pointMaterial, - Constract.MAX_MEASURE_INSTANCES) - ) - } - - get lineSegmentManager(): LineSegmentManager { - if (!this.tempViewport) { - throw new Error('tempViewport is not set.') - } - return this.tempViewport.getOrCreateLineManager(this.itemTypeName, () => - // 构建 LineSegment.points 代理对象 - LineSegmentManager.create(this.itemTypeName, - this.tempViewport, - this.lineMaterial) - ) - } - /** * 所有的点,必须使用同一个尺寸, 改属性也无效 */ @@ -109,6 +83,32 @@ export default class MeasureRenderer extends BaseRenderer { this.tempViewport.labelManager.removeLabel(object) } + get pointManager(): InstancePointManager { + if (!this.tempViewport) { + throw new Error('tempViewport is not set.') + } + return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () => + // 构建 InstanceMesh 代理对象 + InstancePointManager.create(this.itemTypeName, + this.tempViewport, + this.pointGeometry, + this.pointMaterial, + Constract.MAX_MEASURE_INSTANCES) + ) + } + + get lineSegmentManager(): LineSegmentManager { + if (!this.tempViewport) { + throw new Error('tempViewport is not set.') + } + return this.tempViewport.getOrCreateLineManager(this.itemTypeName, () => + // 构建 LineSegment.points 代理对象 + LineSegmentManager.create(this.itemTypeName, + this.tempViewport, + this.lineMaterial) + ) + } + dispose() { super.dispose() this.pointMaterial?.dispose() diff --git a/src/modules/way/WayRenderer.ts b/src/modules/way/WayRenderer.ts index b01ebeb..014e640 100644 --- a/src/modules/way/WayRenderer.ts +++ b/src/modules/way/WayRenderer.ts @@ -1,23 +1,32 @@ import * as THREE from 'three' import BaseRenderer from '@/core/base/BaseRenderer.ts' -import { Text } from 'troika-three-text' import MoveLinePointPng from '@/assets/images/moveline_point.png' -import SimSunTTF from '@/assets/fonts/simsunb.ttf' -import { getLineId } from '@/core/ModelUtils.ts' -import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer' -import { numberToString } from '@/utils/webutils.ts' +import { getLineId, linkPlaneByPoint } from '@/core/ModelUtils.ts' import Constract from '@/core/Constract.ts' -import type { ExtrudeGeometryOptions } from 'three/src/geometries/ExtrudeGeometry' +import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts' +import type { Object3DLike } from '@/types/ModelTypes.ts' +import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' +import LineSegmentManager from '@/core/manager/LineSegmentManager.ts' /** - * 辅助测量工具渲染器 + * AGV行走路线渲染器 point 是二维码站点 */ export default class WayRenderer extends BaseRenderer { static LABEL_NAME = 'way_label' static POINT_NAME = 'way_point' static LINE_NAME = 'way_line' + pointGeometry: THREE.BufferGeometry pointMaterial: THREE.Material + // lineMaterial: LineMaterial = new LineMaterial({ + // color: 0xa0cfff, + // linewidth: 0.8, + // vertexColors: false, + // dashed: false, + // gapSize: 0, + // worldUnits: true + // }) + lineGeometry: THREE.BufferGeometry = new THREE.PlaneGeometry(1, 1).rotateX(-Math.PI / 2) lineMaterial = new THREE.MeshBasicMaterial({ color: 0xa0cfff, transparent: true, @@ -29,149 +38,86 @@ export default class WayRenderer extends BaseRenderer { * 默认点的高度, 防止和地面重合 */ readonly defulePositionY: number = Constract.HEIGHT_WAY - readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.25, 0.25, 0.1) - readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(90, 0, 0) - - constructor(itemTypeName: string) { - super(itemTypeName) + readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.5, 0.1, 0.5) + readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0) + readonly rendererOption = { + lineWidth: 0.8 } async init() { return Promise.all([ super.init(), - this.loadFont() - ]) - } - - async loadFont() { - return new Promise((resolve, reject) => { - new THREE.TextureLoader().load( - MoveLinePointPng, - (texture) => { - this.pointMaterial = new THREE.SpriteMaterial({ - map: texture, - transparent: true, - side: THREE.DoubleSide - }) - resolve() - }, - undefined, - function(err) { - reject(err) - } - ) - }) - } - - /** - * 所有的点,必须使用同一个尺寸, 改属性也无效 - */ - override afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: THREE.Object3D) { - super.afterCreateOrUpdatePoint(item, option, object) - - const point = object - point.position.y = this.defulePositionY - point.scale.set(this.defaultScale.x, this.defaultScale.y, this.defaultScale.z) - point.rotation.set( - THREE.MathUtils.degToRad(this.defaultRotation.x), - THREE.MathUtils.degToRad(this.defaultRotation.y), - THREE.MathUtils.degToRad(this.defaultRotation.z) - ) - } - - private _createOrUpdateLine(startPosition: THREE.Vector3, endPosition: THREE.Vector3, type: LinkType) { - const width = 1 - const halfWidth = width / 2 + new THREE.TextureLoader().loadAsync(MoveLinePointPng) - const path = new THREE.LineCurve3( - new THREE.Vector3(startPosition.x, startPosition.z, halfWidth - Constract.HEIGHT_WAY_LINE), - new THREE.Vector3(endPosition.x, endPosition.z, halfWidth - Constract.HEIGHT_WAY_LINE) - ) + ]).then(([_, texture]) => { + texture.flipY = false - const shape = new THREE.Shape() - shape.moveTo(halfWidth, -halfWidth) - shape.lineTo(halfWidth, halfWidth) - - const extrudeSettings: ExtrudeGeometryOptions = { - steps: 2, // 沿路径的分段数 - depth: 1, // 实际由路径长度决定 - bevelEnabled: false, // 禁用倒角 - extrudePath: path // 挤出路径 - } + this.pointGeometry = new THREE.PlaneGeometry(1, 1).rotateX(-Math.PI / 2) + this.pointGeometry.center() - const extrudedGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings) - extrudedGeometry.rotateX(Math.PI / 2) - - return new THREE.Mesh(extrudedGeometry, this.lineMaterial) + this.pointMaterial = new THREE.MeshBasicMaterial({ + map: texture, + transparent: true, + depthWrite: false, + side: THREE.DoubleSide + }) + this.pointMaterial.needsUpdate = true + }) } - createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D { - const startPosition = new THREE.Vector3(start.tf[0][0], 0, start.tf[0][2]) - const endPosition = new THREE.Vector3(end.tf[0][0], 0, end.tf[0][2]) - - const group = new THREE.Group() - const lineMesh = this._createOrUpdateLine(startPosition, endPosition, type) - group.add(lineMesh) - - - const midPoint = new THREE.Vector3() - .addVectors(startPosition, endPosition) - .multiplyScalar(0.5) - - const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0) + createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike { + // 不允许改变高度/角度/大小 + item.tf = [ + [item.tf[0][0], this.defulePositionY, item.tf[0][2]], + [this.defaultRotation.x, this.defaultRotation.y, this.defaultRotation.z], + [this.defaultScale.x, this.defaultScale.y, this.defaultScale.z] + ] + return this.pointManager.createPoint(item) + } - const label = new Text() - label.text = distance - label.font = SimSunTTF - label.fontSize = 0.2 - label.color = '#5f5f5f' - label.opacity = 0.8 - label.anchorX = 'center' - label.anchorY = 'middle' - label.depthOffset = 1 - label.material.depthTest = false - label.name = WayRenderer.LABEL_NAME - label.quaternion.copy(this.tempViewport.camera.quaternion) - label.sync() - label.position.set(midPoint.x, Constract.HEIGHT_WAY_LABEL, midPoint.z) + createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike { + const lineId = getLineId(start.id, end.id, type) - group.add(label) + // 用 PlaneGeometry 替代线段 + const startPosition = new THREE.Vector3(start.tf[0][0], this.defulePositionY, start.tf[0][2]) + const endPosition = new THREE.Vector3(end.tf[0][0], this.defulePositionY, end.tf[0][2]) - return group + const wrap = this.lineManager.createPointSimple(lineId) + const matrix = linkPlaneByPoint(startPosition, endPosition, this.rendererOption.lineWidth) + wrap.applyMatrix4(matrix) + return wrap } updateLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) { - super.updateLine(start, end, type, option) - - const startPosition = new THREE.Vector3(start.tf[0][0], 0.01, start.tf[0][2]) - const endPosition = new THREE.Vector3(end.tf[0][0], 0.01, end.tf[0][2]) - const lineId = getLineId(start.id, end.id, type) - const group = this.tempViewport.entityManager.findLineObjectById(lineId) - // 清空group里的元素 - const label: Text = group.children[1] - group.clear() + const startPosition = new THREE.Vector3(start.tf[0][0], this.defulePositionY, start.tf[0][2]) + const endPosition = new THREE.Vector3(end.tf[0][0], this.defulePositionY, end.tf[0][2]) + + const wrap = this.tempViewport.entityManager.findLineObjectById(lineId) as PointManageWrap + const matrix = linkPlaneByPoint(startPosition, endPosition, this.rendererOption.lineWidth) + wrap.applyMatrix4(matrix) + } - const lineMesh = this._createOrUpdateLine(startPosition, endPosition, type) - group.add(lineMesh) + afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) { + super.afterCreateOrUpdateLine(start, end, type, option, object) - const midPoint = new THREE.Vector3() - .addVectors(startPosition, endPosition) - .multiplyScalar(0.5) + const startPoint = this.tempViewport?.entityManager.findObjectById(start.id) + const endPoint = this.tempViewport?.entityManager.findObjectById(end.id) - const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0) - label.text = distance - label.quaternion.copy(this.tempViewport.camera.quaternion) - label.sync() - label.position.set(midPoint.x, midPoint.y, midPoint.z) - group.add(label) + this.tempViewport.labelManager.createOrUpdateLabelByDistance(object, startPoint.position, endPoint.position, { + useHtmlLabel: false, + fontSize: 0.2, + color: '#333333', + format: (distance) => { + return (distance * 1000).toFixed(0) + } + }) } - createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D { - const obj = new THREE.Sprite(this.pointMaterial as THREE.SpriteMaterial) - obj.name = WayRenderer.POINT_NAME - return obj + afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) { + super.afterDeleteLine(start, end, type, option, object) + this.tempViewport.labelManager.removeLabel(object) } dispose() { @@ -179,4 +125,32 @@ export default class WayRenderer extends BaseRenderer { this.pointMaterial?.dispose() this.lineMaterial?.dispose() } + + get lineManager(): InstancePointManager { + if (!this.tempViewport) { + throw new Error('tempViewport is not set.') + } + return this.tempViewport.getOrCreatePointManager(this.itemTypeName + '_line', () => + // 构建 LineSegment.points 代理对象 + InstancePointManager.create(this.itemTypeName + '_line', + this.tempViewport, + this.lineGeometry, + this.lineMaterial, + Constract.MAX_WAY_LINE_INSTANCES) + ) + } + + get pointManager(): InstancePointManager { + if (!this.tempViewport) { + throw new Error('tempViewport is not set.') + } + return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () => + // 构建 InstanceMesh 代理对象 + InstancePointManager.create(this.itemTypeName, + this.tempViewport, + this.pointGeometry, + this.pointMaterial, + Constract.MAX_WAY_INSTANCES) + ) + } }