|
|
@ -1,10 +1,11 @@ |
|
|
import * as THREE from 'three' |
|
|
import * as THREE from 'three' |
|
|
import BaseRenderer from '@/core/base/BaseRenderer.ts' |
|
|
import BaseRenderer from '@/core/base/BaseRenderer.ts' |
|
|
import MoveLinePointPng from '@/assets/images/moveline_point.png' |
|
|
import MoveLinePointPng from '@/assets/images/moveline_point.png' |
|
|
import { getLineId, linkPlaneByPoint } from '@/core/ModelUtils.ts' |
|
|
import { getLineId, getMatrixFromTf, linkPlaneByPoint } from '@/core/ModelUtils.ts' |
|
|
import Constract from '@/core/Constract.ts' |
|
|
import Constract from '@/core/Constract.ts' |
|
|
import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts' |
|
|
import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts' |
|
|
import type { Object3DLike } from '@/types/ModelTypes.ts' |
|
|
import type { Object3DLike } from '@/types/ModelTypes.ts' |
|
|
|
|
|
import TriangleUrl from '@/assets/images/conveyor/shapes/triangle.png' |
|
|
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' |
|
|
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' |
|
|
import LineSegmentManager from '@/core/manager/LineSegmentManager.ts' |
|
|
import LineSegmentManager from '@/core/manager/LineSegmentManager.ts' |
|
|
|
|
|
|
|
|
@ -33,6 +34,8 @@ export default class WayRenderer extends BaseRenderer { |
|
|
opacity: 0.2, |
|
|
opacity: 0.2, |
|
|
side: THREE.DoubleSide |
|
|
side: THREE.DoubleSide |
|
|
}) |
|
|
}) |
|
|
|
|
|
dirGeometry: THREE.PlaneGeometry |
|
|
|
|
|
dirMaterial: THREE.Material |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 默认点的高度, 防止和地面重合 |
|
|
* 默认点的高度, 防止和地面重合 |
|
|
@ -47,9 +50,10 @@ export default class WayRenderer extends BaseRenderer { |
|
|
async init() { |
|
|
async init() { |
|
|
return Promise.all([ |
|
|
return Promise.all([ |
|
|
super.init(), |
|
|
super.init(), |
|
|
new THREE.TextureLoader().loadAsync(MoveLinePointPng) |
|
|
new THREE.TextureLoader().loadAsync(MoveLinePointPng), |
|
|
|
|
|
new THREE.TextureLoader().loadAsync(TriangleUrl) |
|
|
|
|
|
|
|
|
]).then(([_, texture]) => { |
|
|
]).then(([_, texture, dirTexture]) => { |
|
|
texture.flipY = false |
|
|
texture.flipY = false |
|
|
|
|
|
|
|
|
this.pointGeometry = new THREE.PlaneGeometry(1, 1).rotateX(-Math.PI / 2) |
|
|
this.pointGeometry = new THREE.PlaneGeometry(1, 1).rotateX(-Math.PI / 2) |
|
|
@ -62,6 +66,19 @@ export default class WayRenderer extends BaseRenderer { |
|
|
side: THREE.DoubleSide |
|
|
side: THREE.DoubleSide |
|
|
}) |
|
|
}) |
|
|
this.pointMaterial.needsUpdate = true |
|
|
this.pointMaterial.needsUpdate = true |
|
|
|
|
|
|
|
|
|
|
|
this.dirGeometry = new THREE.PlaneGeometry(1, 1) |
|
|
|
|
|
this.dirGeometry.rotateX(-Math.PI / 2) |
|
|
|
|
|
.rotateY(Math.PI / 2) |
|
|
|
|
|
this.dirGeometry.center() |
|
|
|
|
|
|
|
|
|
|
|
this.dirMaterial = new THREE.MeshBasicMaterial({ |
|
|
|
|
|
map: dirTexture, |
|
|
|
|
|
transparent: true, |
|
|
|
|
|
opacity: 1, |
|
|
|
|
|
depthWrite: false, |
|
|
|
|
|
side: THREE.DoubleSide |
|
|
|
|
|
}) |
|
|
}) |
|
|
}) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -100,24 +117,77 @@ export default class WayRenderer extends BaseRenderer { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) { |
|
|
afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) { |
|
|
super.afterCreateOrUpdateLine(start, end, type, option, object) |
|
|
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]) |
|
|
|
|
|
|
|
|
|
|
|
// =============== 下面这一段不要删除,用来显示数字标签 =============================
|
|
|
|
|
|
// this.tempViewport.labelManager.createOrUpdateLabelByDistance(object, startPoint.position, endPoint.position, {
|
|
|
|
|
|
// useHtmlLabel: false,
|
|
|
|
|
|
// fontSize: 0.2,
|
|
|
|
|
|
// color: '#333333',
|
|
|
|
|
|
// format: (distance) => {
|
|
|
|
|
|
// return (distance * 1000).toFixed(0)
|
|
|
|
|
|
// }
|
|
|
|
|
|
// })
|
|
|
|
|
|
// ==========================================================================
|
|
|
|
|
|
|
|
|
|
|
|
const matrix = linkPlaneByPoint(startPosition, endPosition, this.rendererOption.lineWidth) |
|
|
|
|
|
|
|
|
const startPoint = this.tempViewport?.entityManager.findObjectById(start.id) |
|
|
if (object.userData.dirWraps) { |
|
|
const endPoint = this.tempViewport?.entityManager.findObjectById(end.id) |
|
|
// 清空之前的箭头
|
|
|
|
|
|
object.userData.dirWraps.forEach((uuid: string) => { |
|
|
|
|
|
this.dirPointManager.deletePoint(uuid) |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
this.tempViewport.labelManager.createOrUpdateLabelByDistance(object, startPoint.position, endPoint.position, { |
|
|
const length = startPosition.distanceTo(endPosition) |
|
|
useHtmlLabel: false, |
|
|
if (length < 0.1) { |
|
|
fontSize: 0.2, |
|
|
// 如果两点距离小于 0.1m,则不添加方向指示器
|
|
|
color: '#333333', |
|
|
return |
|
|
format: (distance) => { |
|
|
|
|
|
return (distance * 1000).toFixed(0) |
|
|
} else if (length < 3) { |
|
|
|
|
|
// 如果两点距离小于 3m,则在中间添加一个方向指示器
|
|
|
|
|
|
const dirWrap = this.dirPointManager.createPointSimple(object.uuid + '_dir') |
|
|
|
|
|
dirWrap.position.setFromMatrixPosition(matrix) |
|
|
|
|
|
dirWrap.rotation.setFromRotationMatrix(matrix) |
|
|
|
|
|
dirWrap.scale.set(0.4, 0.01, 0.2) |
|
|
|
|
|
dirWrap.manager.syncMeshObject3D(dirWrap) |
|
|
|
|
|
|
|
|
|
|
|
object.userData.dirWraps = [dirWrap.uuid] |
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
// 否则每隔 3m 添加一个方向指示器
|
|
|
|
|
|
for (let i = 0; i < length; i += 3) { |
|
|
|
|
|
const dirWrap = this.dirPointManager.createPointSimple(object.uuid + '_dir_' + i) |
|
|
|
|
|
const position = startPosition.clone().lerp(endPosition, i / length) |
|
|
|
|
|
const dummy = new THREE.Object3D() |
|
|
|
|
|
dummy.position.copy(position) |
|
|
|
|
|
dummy.lookAt(endPosition) |
|
|
|
|
|
dummy.scale.set(0.4, 0.01, 0.2) |
|
|
|
|
|
dummy.updateMatrix() |
|
|
|
|
|
|
|
|
|
|
|
dirWrap.applyMatrix4(dummy.matrix) |
|
|
|
|
|
|
|
|
|
|
|
if (!object.userData.dirWraps) { |
|
|
|
|
|
object.userData.dirWraps = [] |
|
|
|
|
|
} |
|
|
|
|
|
object.userData.dirWraps.push(dirWrap.uuid) |
|
|
} |
|
|
} |
|
|
}) |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) { |
|
|
afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) { |
|
|
super.afterDeleteLine(start, end, type, option, object) |
|
|
// =============== 下面这一段不要删除,用来显示数字标签 =============================
|
|
|
this.tempViewport.labelManager.removeLabel(object) |
|
|
// super.afterDeleteLine(start, end, type, option, object)
|
|
|
|
|
|
// this.tempViewport.labelManager.removeLabel(object)
|
|
|
|
|
|
// ==========================================================================
|
|
|
|
|
|
|
|
|
|
|
|
if (object.userData.dirWraps) { |
|
|
|
|
|
// 清空之前的箭头
|
|
|
|
|
|
object.userData.dirWraps.forEach((uuid: string) => { |
|
|
|
|
|
this.dirPointManager.deletePoint(uuid) |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
dispose() { |
|
|
dispose() { |
|
|
@ -153,4 +223,18 @@ export default class WayRenderer extends BaseRenderer { |
|
|
Constract.MAX_WAY_INSTANCES) |
|
|
Constract.MAX_WAY_INSTANCES) |
|
|
) |
|
|
) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
get dirPointManager(): InstancePointManager { |
|
|
|
|
|
if (!this.tempViewport) { |
|
|
|
|
|
throw new Error('tempViewport is not set.') |
|
|
|
|
|
} |
|
|
|
|
|
return this.tempViewport.getOrCreatePointManager(this.itemTypeName + '_dir', () => |
|
|
|
|
|
// 构建 InstanceMesh 代理对象
|
|
|
|
|
|
InstancePointManager.create(this.itemTypeName + '_dir', |
|
|
|
|
|
this.tempViewport, |
|
|
|
|
|
this.dirGeometry, |
|
|
|
|
|
this.dirMaterial, |
|
|
|
|
|
Constract.MAX_WAY_LINE_INSTANCES) |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|