You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
8.4 KiB
241 lines
8.4 KiB
import * as THREE from 'three'
|
|
import BaseRenderer from '@/core/base/BaseRenderer.ts'
|
|
import MoveLinePointPng from '@/assets/images/moveline_point.png'
|
|
import { getLineId, linkPlaneByPoint } from '@/core/ModelUtils.ts'
|
|
import Constract from '@/core/Constract.ts'
|
|
import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
|
|
import type { Object3DLike } from '@/types/ModelTypes.ts'
|
|
import TriangleUrl from '@/assets/images/conveyor/shapes/triangle.png'
|
|
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.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,
|
|
opacity: 0.2,
|
|
side: THREE.DoubleSide
|
|
})
|
|
dirGeometry: THREE.PlaneGeometry
|
|
dirMaterial: THREE.Material
|
|
|
|
/**
|
|
* 默认点的高度, 防止和地面重合
|
|
*/
|
|
readonly defulePositionY: number = Constract.HEIGHT_WAY
|
|
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(),
|
|
new THREE.TextureLoader().loadAsync(MoveLinePointPng),
|
|
new THREE.TextureLoader().loadAsync(TriangleUrl)
|
|
|
|
]).then(([_, texture, dirTexture]) => {
|
|
texture.flipY = false
|
|
|
|
this.pointGeometry = new THREE.PlaneGeometry(1, 1).rotateX(-Math.PI / 2)
|
|
this.pointGeometry.center()
|
|
|
|
this.pointMaterial = new THREE.MeshBasicMaterial({
|
|
map: texture,
|
|
transparent: true,
|
|
depthWrite: false,
|
|
side: THREE.DoubleSide
|
|
})
|
|
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
|
|
})
|
|
})
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike {
|
|
const lineId = getLineId(start.id, end.id, type)
|
|
|
|
// 用 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])
|
|
|
|
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) {
|
|
const lineId = getLineId(start.id, end.id, type)
|
|
|
|
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)
|
|
}
|
|
|
|
afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
|
|
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)
|
|
|
|
if (object.userData.dirWraps) {
|
|
// 清空之前的箭头
|
|
object.userData.dirWraps.forEach((uuid: string) => {
|
|
this.dirPointManager.delete(uuid)
|
|
})
|
|
}
|
|
|
|
const length = startPosition.distanceTo(endPosition)
|
|
if (length < 0.1) {
|
|
// 如果两点距离小于 0.1m,则不添加方向指示器
|
|
return
|
|
|
|
} else if (length < 3) {
|
|
// 如果两点距离小于 3m,则在中间添加一个方向指示器
|
|
const dirWrap = this.dirPointManager.create(object.uuid + '_dir')
|
|
|
|
const dummy = new THREE.Object3D()
|
|
dummy.position.setFromMatrixPosition(matrix)
|
|
dummy.rotation.setFromRotationMatrix(matrix)
|
|
dummy.scale.set(0.4, 0.01, 0.2)
|
|
dummy.updateMatrix()
|
|
dirWrap.setMatrix4(dummy.matrix)
|
|
object.userData.dirWraps = [dirWrap.uuid]
|
|
|
|
} else {
|
|
// 否则每隔 3m 添加一个方向指示器
|
|
for (let i = 0; i < length; i += 3) {
|
|
const dirWrap = this.dirPointManager.create(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.setMatrix4(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) {
|
|
// =============== 下面这一段不要删除,用来显示数字标签 =============================
|
|
// super.afterDeleteLine(start, end, type, option, object)
|
|
// this.tempViewport.labelManager.removeLabel(object)
|
|
// ==========================================================================
|
|
|
|
if (object.userData.dirWraps) {
|
|
// 清空之前的箭头
|
|
object.userData.dirWraps.forEach((uuid: string) => {
|
|
this.dirPointManager.delete(uuid)
|
|
})
|
|
}
|
|
}
|
|
|
|
dispose() {
|
|
super.dispose()
|
|
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,
|
|
false, false)
|
|
)
|
|
}
|
|
|
|
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,
|
|
true, true)
|
|
)
|
|
}
|
|
|
|
get dirPointManager(): InstanceMeshManager {
|
|
if (!this.tempViewport) {
|
|
throw new Error('tempViewport is not set.')
|
|
}
|
|
return this.tempViewport.getOrCreateMeshManager(this.itemTypeName + '_dir', () =>
|
|
// 构建 InstanceMesh 代理对象
|
|
new InstanceMeshManager(this.itemTypeName + '_dir',
|
|
this.tempViewport,
|
|
this.dirGeometry,
|
|
this.dirMaterial,
|
|
false, false)
|
|
)
|
|
}
|
|
}
|
|
|