Browse Source

WayRenderer 箭头

master
修宁 6 months ago
parent
commit
bd635ae4bd
  1. 16
      src/core/ModelUtils.ts
  2. 3
      src/core/manager/InstancePointManager.ts
  3. 114
      src/modules/way/WayRenderer.ts

16
src/core/ModelUtils.ts

@ -510,7 +510,8 @@ export function linkPlaneByPoint(startPosition: THREE.Vector3, endPosition: THRE
const dummy = new THREE.Object3D() const dummy = new THREE.Object3D()
dummy.position.copy(center) dummy.position.copy(center)
dummy.quaternion.setFromRotationMatrix(new THREE.Matrix4().lookAt(startPosition, endPosition, new THREE.Vector3(0, 1, 0))) dummy.lookAt(endPosition);
// dummy.quaternion.setFromRotationMatrix(new THREE.Matrix4().lookAt(startPosition, endPosition, new THREE.Vector3(0, 1, 0)))
dummy.scale.set(width, 1, length) // Z轴缩放为长度 dummy.scale.set(width, 1, length) // Z轴缩放为长度
dummy.updateMatrix() dummy.updateMatrix()
return dummy.matrix return dummy.matrix
@ -549,3 +550,16 @@ export function load3DModule(arrayBuffer: ArrayBuffer | string, ext: string) {
return null return null
} }
} }
export function getMatrixFromTf(tf: number[][]): THREE.Matrix4 {
const dummy = new THREE.Object3D()
dummy.position.set(tf[0][0], tf[0][1], tf[0][2])
dummy.rotation.set(
THREE.MathUtils.degToRad(tf[1][0]),
THREE.MathUtils.degToRad(tf[1][1]),
THREE.MathUtils.degToRad(tf[1][2])
)
dummy.scale.set(tf[2][0], tf[2][1], tf[2][2])
dummy.updateMatrix()
return dummy.matrix
}

3
src/core/manager/InstancePointManager.ts

@ -246,7 +246,7 @@ export class PointManageWrap {
this.meshIndex = -1 this.meshIndex = -1
} }
applyMatrix4(matrix: THREE.Matrix4): void { applyMatrix4(matrix: THREE.Matrix4): PointManageWrap {
const position = new THREE.Vector3() const position = new THREE.Vector3()
const quaternion = new THREE.Quaternion() const quaternion = new THREE.Quaternion()
const scale = new THREE.Vector3() const scale = new THREE.Vector3()
@ -256,6 +256,7 @@ export class PointManageWrap {
this.rotation.setFromQuaternion(quaternion) this.rotation.setFromQuaternion(quaternion)
this.scale.copy(scale) this.scale.copy(scale)
this.manager.syncMeshObject3D(this) this.manager.syncMeshObject3D(this)
return this
} }
createBox3(): THREE.Box3 { createBox3(): THREE.Box3 {

114
src/modules/way/WayRenderer.ts

@ -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)
)
}
} }

Loading…
Cancel
Save