Browse Source

Merge remote-tracking branch 'origin/master'

master
yuliang 6 months ago
parent
commit
c12d65cb98
  1. 4
      src/components/Model3DView.vue
  2. 4
      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. 10
      src/core/manager/LineSegmentManager.ts
  9. 23
      src/example/ExampleUtil.js
  10. 18
      src/example/example1.js
  11. 8
      src/modules/carton/CartonRenderer.ts
  12. 52
      src/modules/measure/MeasureRenderer.ts
  13. 228
      src/modules/way/WayRenderer.ts

4
src/components/Model3DView.vue

@ -176,6 +176,9 @@ watch(() => restate.mode, (newVal) => {
} }
}) })
/**
* 添加输送线
*/
function addConveyor() { function addConveyor() {
const conveyorLength = 10 // const conveyorLength = 10 //
const conveyorWidth = 0.8 // const conveyorWidth = 0.8 //
@ -1029,7 +1032,6 @@ function handleFileChange(file) {
const arrayBuffer = reader.result const arrayBuffer = reader.result
//@ts-ignore //@ts-ignore
loader.parseAsync(arrayBuffer, '').then((content) => { loader.parseAsync(arrayBuffer, '').then((content) => {
debugger
addGroupToScene(content.scene) addGroupToScene(content.scene)
}) })

4
src/core/Constract.ts

@ -33,8 +33,10 @@ const Constract = Object.freeze({
HEIGHT_WAY_LABEL: 0.03, HEIGHT_WAY_LABEL: 0.03,
HEIGHT_WAY_LINE: 0.02, HEIGHT_WAY_LINE: 0.02,
MAX_WAY_INSTANCES: 10000,
MAX_WAY_LINE_INSTANCES: 40000,
MAX_MEASURE_INSTANCES: 1000, MAX_MEASURE_INSTANCES: 1000,
MAX_GSTORE_INSTANCES: 10000, MAX_GSTORE_INSTANCES: 10000,
MAX_PALLET_INSTANCES: 10000, MAX_PALLET_INSTANCES: 10000
}) })
export default Constract 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> { export async function loadGlbModule(url: string): Promise<THREE.Group> {
const response = await axios.get(url, { const response = await axios.get(url, {
responseType: 'arraybuffer' responseType: 'arraybuffer'
@ -528,42 +549,3 @@ export function load3DModule(arrayBuffer: ArrayBuffer | string, ext: string) {
return null 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 type Viewport from '@/core/engine/Viewport'
import * as THREE from 'three' 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 { Line2 } from 'three/examples/jsm/lines/Line2'
import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts' import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import Constract from '@/core/Constract.ts' import Constract from '@/core/Constract.ts'
@ -223,11 +223,25 @@ export default abstract class BaseRenderer {
this.tempViewport.entityManager.appendLineObject(id, line) this.tempViewport.entityManager.appendLineObject(id, line)
if (line instanceof THREE.Object3D) { if (line instanceof THREE.Object3D) {
this.appendToScene(line) this.appendToScene(line)
} else if (line instanceof PointManageWrap) {
line.manager.syncMeshObject3D(line)
} }
this.afterCreateOrUpdateLine(start, end, type, option, 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 * @param start
@ -235,10 +249,8 @@ export default abstract class BaseRenderer {
* @param type 线 * @param type 线
* @param option * @param option
*/ */
updateLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) { updateLine(start: ItemJson, end: ItemJson, type: LinkType, option: any) {
const lineId = getLineId(start.id, end.id, type) const { line, lineId } = option
const line = this.tempViewport.entityManager.findLineObjectById(lineId)
const startPoint = this.tempViewport.entityManager.findObjectById(start.id) const startPoint = this.tempViewport.entityManager.findObjectById(start.id)
const endPoint = this.tempViewport.entityManager.findObjectById(end.id) const endPoint = this.tempViewport.entityManager.findObjectById(end.id)
@ -249,8 +261,6 @@ export default abstract class BaseRenderer {
} else if (line instanceof LineManageWrap) { } else if (line instanceof LineManageWrap) {
line.manager.updateLine(lineId, startPoint.position, endPoint.position, line.color) 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 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 // instanceId -> itemId
private __indexIdMap = new Map<number, string>() 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 * @param item
@ -233,6 +246,18 @@ export class PointManageWrap {
this.meshIndex = -1 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 { createBox3(): THREE.Box3 {
const instancedMesh = this.manager.instancedMesh const instancedMesh = this.manager.instancedMesh
const matrix = new THREE.Matrix4() const matrix = new THREE.Matrix4()

7
src/core/manager/LabelManager.ts

@ -28,6 +28,8 @@ export interface LabelOption {
*/ */
padding?: number | string padding?: number | string
text?: string text?: string
format?: (distance: number) => string
} }
/** /**
@ -58,7 +60,10 @@ export default class LabelManager implements IControls {
// 计算距离 // 计算距离
const distance = startPos.distanceTo(endPos) 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) this.updateLabel(lineRef, text)
return labelObj return labelObj

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 { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import type { Object3DLike, Vector3Like } from '@/types/ModelTypes.ts' 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 { export default class LineSegmentManager {
private readonly viewport: Viewport private readonly viewport: Viewport
private readonly lineGeometry: LineSegmentsGeometry private readonly lineGeometry: LineGeometry // LineSegmentsGeometry
private readonly lineMaterial: LineMaterial private readonly lineMaterial: LineMaterial
private readonly lineSegments: LineSegments2 private readonly lineSegments: LineSegments2
private readonly segments: Map<string, LineManageWrap> = new Map() private readonly segments: Map<string, LineManageWrap> = new Map()
@ -242,7 +244,7 @@ export default class LineSegmentManager {
this.lineGeometry.setColors(this.colorArray) 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 this.needsUpdate = false
} }
@ -257,10 +259,10 @@ export default class LineSegmentManager {
this.viewport = viewport this.viewport = viewport
this.lineMaterial = lineMaterial 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.name = name
this.lineSegments.frustumCulled = false this.lineSegments.frustumCulled = false
this.viewport.scene.add(this.lineSegments) this.viewport.scene.add(this.lineSegments)

23
src/example/ExampleUtil.js

@ -68,17 +68,18 @@ export function buildAgvPerformanceData(t, rows, cols) {
} }
} }
data.get('wp_0_0').dt.center.push('wp_0_' + (cols - 1)) // 四个对角连线
data.get('wp_0_' + (cols - 1)).dt.center.push('wp_0_0') // data.get('wp_0_0').dt.center.push('wp_0_' + (cols - 1))
// data.get('wp_0_' + (cols - 1)).dt.center.push('wp_0_0')
data.get('wp_' + (rows - 1) + '_0').dt.center.push('wp_' + (rows - 1) + '_' + (cols - 1)) //
data.get('wp_' + (rows - 1) + '_' + (cols - 1)).dt.center.push('wp_' + (rows - 1) + '_0') // data.get('wp_' + (rows - 1) + '_0').dt.center.push('wp_' + (rows - 1) + '_' + (cols - 1))
// data.get('wp_' + (rows - 1) + '_' + (cols - 1)).dt.center.push('wp_' + (rows - 1) + '_0')
data.get('wp_' + (rows - 1) + '_0').dt.center.push('wp_0_0') //
data.get('wp_0_0').dt.center.push('wp_' + (rows - 1) + '_0') // data.get('wp_' + (rows - 1) + '_0').dt.center.push('wp_0_0')
// data.get('wp_0_0').dt.center.push('wp_' + (rows - 1) + '_0')
data.get('wp_' + (rows - 1) + '_' + (cols - 1)).dt.center.push('wp_0_' + (cols - 1)) //
data.get('wp_0_' + (cols - 1)).dt.center.push('wp_' + (rows - 1) + '_' + (cols - 1)) // data.get('wp_' + (rows - 1) + '_' + (cols - 1)).dt.center.push('wp_0_' + (cols - 1))
// data.get('wp_0_' + (cols - 1)).dt.center.push('wp_' + (rows - 1) + '_' + (cols - 1))
return Array.from(data.values()) return Array.from(data.values())
} }

18
src/example/example1.js

@ -330,13 +330,27 @@ export default {
t: 'carton', t: 'carton',
v: true, v: true,
tf: [[0, 0.1, 0], [0, 0, 0], [1.0, 1.0, 1.0]], 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', catalogCode: '__f1', t: 'floor',
items: buildAgvPerformanceData('measure', 100, 100) items: buildAgvPerformanceData('way', 100, 100)
}, },
{ {
catalogCode: '__f2', t: 'floor', 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.cartonGeometry = mesh.geometry
this.cartonMaterial = new THREE.MeshPhongMaterial({ color: 0xc29a70 }) // mesh.material as THREE.Material this.cartonMaterial = new THREE.MeshPhongMaterial({ color: 0xc29a70 }) // mesh.material as THREE.Material
this.cartonGeometry.scale(0.01, 0.01, 0.01) 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.wrapS = THREE.RepeatWrapping
cartonTexture.wrapT = THREE.RepeatWrapping cartonTexture.wrapT = THREE.RepeatWrapping
cartonTexture.repeat.set(1, 1) cartonTexture.repeat.set(1, -1)
cartonTexture.offset.y = 1
//@ts-ignore //@ts-ignore
this.cartonMaterial.map = cartonTexture this.cartonMaterial.map = cartonTexture
//@ts-ignore //@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 defaultScale: THREE.Vector3 = new THREE.Vector3(0.25, 0.25, 0.1)
readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(90, 0, 0) 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) 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() { dispose() {
super.dispose() super.dispose()
this.pointMaterial?.dispose() this.pointMaterial?.dispose()

228
src/modules/way/WayRenderer.ts

@ -1,23 +1,32 @@
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 { Text } from 'troika-three-text'
import MoveLinePointPng from '@/assets/images/moveline_point.png' import MoveLinePointPng from '@/assets/images/moveline_point.png'
import SimSunTTF from '@/assets/fonts/simsunb.ttf' import { getLineId, linkPlaneByPoint } from '@/core/ModelUtils.ts'
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 Constract from '@/core/Constract.ts'
import type { ExtrudeGeometryOptions } from 'three/src/geometries/ExtrudeGeometry' 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 { export default class WayRenderer extends BaseRenderer {
static LABEL_NAME = 'way_label' static LABEL_NAME = 'way_label'
static POINT_NAME = 'way_point' static POINT_NAME = 'way_point'
static LINE_NAME = 'way_line' static LINE_NAME = 'way_line'
pointGeometry: THREE.BufferGeometry
pointMaterial: THREE.Material 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({ lineMaterial = new THREE.MeshBasicMaterial({
color: 0xa0cfff, color: 0xa0cfff,
transparent: true, transparent: true,
@ -29,149 +38,86 @@ export default class WayRenderer extends BaseRenderer {
* , * ,
*/ */
readonly defulePositionY: number = Constract.HEIGHT_WAY readonly defulePositionY: number = Constract.HEIGHT_WAY
readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.25, 0.25, 0.1) readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.5, 0.1, 0.5)
readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(90, 0, 0) readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0)
readonly rendererOption = {
constructor(itemTypeName: string) { lineWidth: 0.8
super(itemTypeName)
} }
async init() { async init() {
return Promise.all([ return Promise.all([
super.init(), super.init(),
this.loadFont() new THREE.TextureLoader().loadAsync(MoveLinePointPng)
])
}
async loadFont() {
return new Promise<void>((resolve, reject) => {
new THREE.TextureLoader().load(
MoveLinePointPng,
(texture) => {
this.pointMaterial = new THREE.SpriteMaterial({
map: texture,
transparent: true,
side: THREE.DoubleSide
})
resolve()
},
undefined,
function(err) {
reject(err)
}
)
})
}
/**
* 使,
*/
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)
)
}
private _createOrUpdateLine(startPosition: THREE.Vector3, endPosition: THREE.Vector3, type: LinkType) {
const width = 1
const halfWidth = width / 2
const path = new THREE.LineCurve3( ]).then(([_, texture]) => {
new THREE.Vector3(startPosition.x, startPosition.z, halfWidth - Constract.HEIGHT_WAY_LINE), texture.flipY = false
new THREE.Vector3(endPosition.x, endPosition.z, halfWidth - Constract.HEIGHT_WAY_LINE)
)
const shape = new THREE.Shape() this.pointGeometry = new THREE.PlaneGeometry(1, 1).rotateX(-Math.PI / 2)
shape.moveTo(halfWidth, -halfWidth) this.pointGeometry.center()
shape.lineTo(halfWidth, halfWidth)
const extrudeSettings: ExtrudeGeometryOptions = {
steps: 2, // 沿路径的分段数
depth: 1, // 实际由路径长度决定
bevelEnabled: false, // 禁用倒角
extrudePath: path // 挤出路径
}
const extrudedGeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings) this.pointMaterial = new THREE.MeshBasicMaterial({
extrudedGeometry.rotateX(Math.PI / 2) map: texture,
transparent: true,
return new THREE.Mesh(extrudedGeometry, this.lineMaterial) depthWrite: false,
side: THREE.DoubleSide
})
this.pointMaterial.needsUpdate = true
})
} }
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D { createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike {
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]) item.tf = [
[item.tf[0][0], this.defulePositionY, item.tf[0][2]],
const group = new THREE.Group() [this.defaultRotation.x, this.defaultRotation.y, this.defaultRotation.z],
const lineMesh = this._createOrUpdateLine(startPosition, endPosition, type) [this.defaultScale.x, this.defaultScale.y, this.defaultScale.z]
group.add(lineMesh) ]
return this.pointManager.createPoint(item)
}
const midPoint = new THREE.Vector3()
.addVectors(startPosition, endPosition)
.multiplyScalar(0.5)
const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0)
const label = new Text() createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike {
label.text = distance const lineId = getLineId(start.id, end.id, type)
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) // 用 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])
return group 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) { 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 lineId = getLineId(start.id, end.id, type)
const group = this.tempViewport.entityManager.findLineObjectById(lineId)
// 清空group里的元素 const startPosition = new THREE.Vector3(start.tf[0][0], this.defulePositionY, start.tf[0][2])
const label: Text = group.children[1] const endPosition = new THREE.Vector3(end.tf[0][0], this.defulePositionY, end.tf[0][2])
group.clear()
const wrap = this.tempViewport.entityManager.findLineObjectById(lineId) as PointManageWrap
const matrix = linkPlaneByPoint(startPosition, endPosition, this.rendererOption.lineWidth)
wrap.applyMatrix4(matrix)
}
const lineMesh = this._createOrUpdateLine(startPosition, endPosition, type) afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
group.add(lineMesh) super.afterCreateOrUpdateLine(start, end, type, option, object)
const midPoint = new THREE.Vector3() const startPoint = this.tempViewport?.entityManager.findObjectById(start.id)
.addVectors(startPosition, endPosition) const endPoint = this.tempViewport?.entityManager.findObjectById(end.id)
.multiplyScalar(0.5)
const distance = (startPosition.distanceTo(endPosition) * 1000).toFixed(0) this.tempViewport.labelManager.createOrUpdateLabelByDistance(object, startPoint.position, endPoint.position, {
label.text = distance useHtmlLabel: false,
label.quaternion.copy(this.tempViewport.camera.quaternion) fontSize: 0.2,
label.sync() color: '#333333',
label.position.set(midPoint.x, midPoint.y, midPoint.z) format: (distance) => {
group.add(label) return (distance * 1000).toFixed(0)
}
})
} }
createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D { afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
const obj = new THREE.Sprite(this.pointMaterial as THREE.SpriteMaterial) super.afterDeleteLine(start, end, type, option, object)
obj.name = WayRenderer.POINT_NAME this.tempViewport.labelManager.removeLabel(object)
return obj
} }
dispose() { dispose() {
@ -179,4 +125,32 @@ export default class WayRenderer extends BaseRenderer {
this.pointMaterial?.dispose() this.pointMaterial?.dispose()
this.lineMaterial?.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,
Constract.MAX_WAY_LINE_INSTANCES)
)
}
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_WAY_INSTANCES)
)
}
} }

Loading…
Cancel
Save