diff --git a/src/components/Model3DView.vue b/src/components/Model3DView.vue index a93385d..9b75bac 100644 --- a/src/components/Model3DView.vue +++ b/src/components/Model3DView.vue @@ -870,7 +870,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..81d1932 100644 --- a/src/core/Constract.ts +++ b/src/core/Constract.ts @@ -33,6 +33,7 @@ const Constract = Object.freeze({ HEIGHT_WAY_LABEL: 0.03, HEIGHT_WAY_LINE: 0.02, + MAX_WAY_INSTANCES: 10000, MAX_MEASURE_INSTANCES: 1000, MAX_GSTORE_INSTANCES: 10000, MAX_PALLET_INSTANCES: 10000, 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/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..57d89b6 100644 --- a/src/modules/way/WayRenderer.ts +++ b/src/modules/way/WayRenderer.ts @@ -4,10 +4,12 @@ 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 Constract from '@/core/Constract.ts' import type { ExtrudeGeometryOptions } from 'three/src/geometries/ExtrudeGeometry' +import InstancePointManager 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' /** * 辅助测量工具渲染器 @@ -17,166 +19,184 @@ export default class WayRenderer extends BaseRenderer { static POINT_NAME = 'way_point' static LINE_NAME = 'way_line' + pointGeometry: THREE.BufferGeometry pointMaterial: THREE.Material - lineMaterial = new THREE.MeshBasicMaterial({ + lineMaterial: LineMaterial = new LineMaterial({ color: 0xa0cfff, - transparent: true, - opacity: 0.2, - side: THREE.DoubleSide + linewidth: 0.8, + vertexColors: false, + dashed: false, + gapSize: 0, + worldUnits: true }) + // lineMaterial = new THREE.MeshBasicMaterial({ + // color: 0xa0cfff, + // transparent: true, + // opacity: 0.2, + // side: THREE.DoubleSide + // }) /** * 默认点的高度, 防止和地面重合 */ 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) 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 - - 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) - ) + new THREE.TextureLoader().loadAsync(MoveLinePointPng) - const shape = new THREE.Shape() - shape.moveTo(halfWidth, -halfWidth) - shape.lineTo(halfWidth, halfWidth) + ]).then(([_, texture]) => { + texture.flipY = false - const extrudeSettings: ExtrudeGeometryOptions = { - steps: 2, // 沿路径的分段数 - depth: 1, // 实际由路径长度决定 - bevelEnabled: false, // 禁用倒角 - extrudePath: path // 挤出路径 - } - - const extrudedGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings) - extrudedGeometry.rotateX(Math.PI / 2) + this.pointGeometry = new THREE.PlaneGeometry(1, 1).rotateX(-Math.PI / 2) + this.pointGeometry.center() - 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) - - 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) - - group.add(label) - - return group + 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) } - 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]) - + createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike { 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 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) - label.text = distance - label.quaternion.copy(this.tempViewport.camera.quaternion) - label.sync() - label.position.set(midPoint.x, midPoint.y, midPoint.z) - group.add(label) + return this.lineSegmentManager.createLine(lineId, start.tf[0], end.tf[0], this.lineMaterial.color) } - createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D { - const obj = new THREE.Sprite(this.pointMaterial as THREE.SpriteMaterial) - obj.name = WayRenderer.POINT_NAME - return obj - } + // private _createOrUpdateLine(startPosition: THREE.Vector3, endPosition: THREE.Vector3, type: LinkType) { + // const width = 1 + // const halfWidth = width / 2 + // + // 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) + // ) + // + // const shape = new THREE.Shape() + // shape.moveTo(halfWidth, -halfWidth) + // shape.lineTo(halfWidth, halfWidth) + // + // const extrudeSettings: ExtrudeGeometryOptions = { + // steps: 2, // 沿路径的分段数 + // depth: 1, // 实际由路径长度决定 + // bevelEnabled: false, // 禁用倒角 + // extrudePath: path // 挤出路径 + // } + // + // const extrudedGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings) + // extrudedGeometry.rotateX(Math.PI / 2) + // + // return new THREE.Mesh(extrudedGeometry, this.lineMaterial) + // } + + // 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) + // + // 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) + // + // group.add(label) + // + // return group + // } + // + // 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 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) + // label.text = distance + // label.quaternion.copy(this.tempViewport.camera.quaternion) + // label.sync() + // label.position.set(midPoint.x, midPoint.y, midPoint.z) + // group.add(label) + // } dispose() { super.dispose() this.pointMaterial?.dispose() this.lineMaterial?.dispose() } + + 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) + ) + } + + 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) + ) + } }