Browse Source

WayRenderer PanelGeometry 替代 Line

master
修宁 6 months ago
parent
commit
0b6f551a68
  1. 3
      src/components/Model3DView.vue
  2. 3
      src/core/Constract.ts
  3. 60
      src/core/ModelUtils.ts
  4. 24
      src/core/base/BaseRenderer.ts
  5. 2
      src/core/manager/EntityManager.ts
  6. 25
      src/core/manager/InstancePointManager.ts
  7. 7
      src/core/manager/LabelManager.ts
  8. 176
      src/modules/way/WayRenderer.ts

3
src/components/Model3DView.vue

@ -176,6 +176,9 @@ watch(() => restate.mode, (newVal) => {
}
})
/**
* 添加输送线
*/
function addConveyor() {
const conveyorLength = 10 //
const conveyorWidth = 0.8 //

3
src/core/Constract.ts

@ -34,8 +34,9 @@ const Constract = Object.freeze({
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

60
src/core/ModelUtils.ts

@ -495,6 +495,27 @@ export async function loadByUrl(url): Promise<any> {
})
}
/**
* , 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<THREE.Group> {
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
}

24
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)
}
/**

2
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)
}
// "线"删除

25
src/core/manager/InstancePointManager.ts

@ -19,6 +19,19 @@ export default class InstancePointManager {
// instanceId -> itemId
private __indexIdMap = new Map<number, string>()
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()

7
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

176
src/modules/way/WayRenderer.ts

@ -1,18 +1,15 @@
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 { getLineId, linkPlaneByPoint } from '@/core/ModelUtils.ts'
import Constract from '@/core/Constract.ts'
import type { ExtrudeGeometryOptions } from 'three/src/geometries/ExtrudeGeometry'
import InstancePointManager from '@/core/manager/InstancePointManager.ts'
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'
@ -21,20 +18,21 @@ export default class WayRenderer extends BaseRenderer {
pointGeometry: THREE.BufferGeometry
pointMaterial: THREE.Material
lineMaterial: LineMaterial = new LineMaterial({
color: 0xa0cfff,
linewidth: 0.8,
vertexColors: false,
dashed: false,
gapSize: 0,
worldUnits: true
})
// 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
// })
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
})
/**
* ,
@ -42,6 +40,9 @@ export default class WayRenderer extends BaseRenderer {
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([
@ -76,97 +77,48 @@ export default class WayRenderer extends BaseRenderer {
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike {
const lineId = getLineId(start.id, end.id, type)
return this.lineSegmentManager.createLine(lineId, start.tf[0], end.tf[0], this.lineMaterial.color)
// 用 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)
}
// 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)
// }
afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
super.afterCreateOrUpdateLine(start, end, type, option, object)
const startPoint = this.tempViewport?.entityManager.findObjectById(start.id)
const endPoint = this.tempViewport?.entityManager.findObjectById(end.id)
this.tempViewport.labelManager.createOrUpdateLabelByDistance(object, startPoint.position, endPoint.position, {
useHtmlLabel: false,
fontSize: 0.2,
color: '#333333',
format: (distance) => {
return (distance * 1000).toFixed(0)
}
})
}
afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
super.afterDeleteLine(start, end, type, option, object)
this.tempViewport.labelManager.removeLabel(object)
}
dispose() {
super.dispose()
@ -174,15 +126,17 @@ export default class WayRenderer extends BaseRenderer {
this.lineMaterial?.dispose()
}
get lineSegmentManager(): LineSegmentManager {
get lineManager(): InstancePointManager {
if (!this.tempViewport) {
throw new Error('tempViewport is not set.')
}
return this.tempViewport.getOrCreateLineManager(this.itemTypeName, () =>
return this.tempViewport.getOrCreatePointManager(this.itemTypeName + '_line', () =>
// 构建 LineSegment.points 代理对象
LineSegmentManager.create(this.itemTypeName,
InstancePointManager.create(this.itemTypeName + '_line',
this.tempViewport,
this.lineMaterial)
this.lineGeometry,
this.lineMaterial,
Constract.MAX_WAY_LINE_INSTANCES)
)
}

Loading…
Cancel
Save