Browse Source

WayRenderer 性能优化, 压力测试

master
修宁 6 months ago
parent
commit
9e054f572a
  1. 1
      src/components/Model3DView.vue
  2. 1
      src/core/Constract.ts
  3. 10
      src/core/manager/LineSegmentManager.ts
  4. 18
      src/example/example1.js
  5. 8
      src/modules/carton/CartonRenderer.ts
  6. 52
      src/modules/measure/MeasureRenderer.ts
  7. 284
      src/modules/way/WayRenderer.ts

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

1
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,

10
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<string, LineManageWrap> = 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)

18
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',

8
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

52
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()

284
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()
])
}
new THREE.TextureLoader().loadAsync(MoveLinePointPng)
]).then(([_, texture]) => {
texture.flipY = false
async loadFont() {
return new Promise<void>((resolve, reject) => {
new THREE.TextureLoader().load(
MoveLinePointPng,
(texture) => {
this.pointMaterial = new THREE.SpriteMaterial({
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
})
resolve()
},
undefined,
function(err) {
reject(err)
}
)
this.pointMaterial.needsUpdate = true
})
}
/**
* 使,
*/
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)
)
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)
}
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 // 挤出路径
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)
}
const extrudedGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings)
extrudedGeometry.rotateX(Math.PI / 2)
// 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)
// }
return new THREE.Mesh(extrudedGeometry, this.lineMaterial)
dispose() {
super.dispose()
this.pointMaterial?.dispose()
this.lineMaterial?.dispose()
}
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
get lineSegmentManager(): LineSegmentManager {
if (!this.tempViewport) {
throw new Error('tempViewport is not set.')
}
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)
return this.tempViewport.getOrCreateLineManager(this.itemTypeName, () =>
// 构建 LineSegment.points 代理对象
LineSegmentManager.create(this.itemTypeName,
this.tempViewport,
this.lineMaterial)
)
}
createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D {
const obj = new THREE.Sprite(this.pointMaterial as THREE.SpriteMaterial)
obj.name = WayRenderer.POINT_NAME
return obj
get pointManager(): InstancePointManager {
if (!this.tempViewport) {
throw new Error('tempViewport is not set.')
}
dispose() {
super.dispose()
this.pointMaterial?.dispose()
this.lineMaterial?.dispose()
return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () =>
// 构建 InstanceMesh 代理对象
InstancePointManager.create(this.itemTypeName,
this.tempViewport,
this.pointGeometry,
this.pointMaterial,
Constract.MAX_WAY_INSTANCES)
)
}
}

Loading…
Cancel
Save