Browse Source

拖拽管理器完成 DragManager

master
修宁 6 months ago
parent
commit
5b59c9e4b6
  1. 4
      README.md
  2. 16
      doc/物流模型总体介绍.md
  3. 14
      src/core/ModelUtils.ts
  4. 3
      src/core/base/BaseInteraction.ts
  5. 1
      src/core/base/BaseRenderer.ts
  6. 3
      src/core/engine/Viewport.ts
  7. 98
      src/core/manager/DragManager.ts
  8. 13
      src/core/manager/InstanceMeshManager.ts
  9. 408
      src/core/manager/InstancePointManager.ts
  10. 5
      src/core/manager/SelectManager.ts
  11. 4
      src/core/manager/StateManager.ts
  12. 3
      src/modules/pallet/PalletRenderer.ts
  13. 1
      src/modules/tote/ToteRenderer.ts
  14. 1
      src/modules/way/WayRenderer.ts

4
README.md

@ -126,10 +126,6 @@ src/
│ │ └── ... │ │ └── ...
│ ├── propEditors/ # 属性面板编辑器 │ ├── propEditors/ # 属性面板编辑器
│ │ └── ... │ │ └── ...
│ ├── controls/ # 各种实体基础类
│ │ ├── SelectionControls.ts
│ │ ├── DragControl.ts
│ │ └── MouseMoveControls.ts
│ ├── Model3DViewer.vue │ ├── Model3DViewer.vue
│ ├── Model2DEditor.vue │ ├── Model2DEditor.vue
│ └── EditorMain.vue # Three.js 封装类 │ └── EditorMain.vue # Three.js 封装类

16
doc/物流模型总体介绍.md

@ -450,9 +450,23 @@ export default class Viewport {
statsControls: Stats statsControls: Stats
controls: OrbitControls controls: OrbitControls
raycaster: THREE.Raycaster raycaster: THREE.Raycaster
dragControl: EsDragControls
animationFrameId: any = null animationFrameId: any = null
selectManager = new SelectManager()
mouseMoveManager = new MouseMoveManager()
dragManager = new DragManager()
labelManager = new LabelManager()
entityManager = new EntityManager()
itemFindManager = new ItemFindManager()
interactionManager = new InteractionManager()
// 状态管理器
stateManager: StateManager
// 对象实例管理器 moduleName -> InstanceMeshManager
meshManager: Map<string, InstanceMeshManager> = new Map()
// 线段实例管理器 moduleName -> LineSegmentManager
lineSegmentManagerMap: Map<string, LineSegmentManager> = new Map()
constructor(sceneHelp: SceneHelp, viewerDom: HTMLElement) constructor(sceneHelp: SceneHelp, viewerDom: HTMLElement)
} }
``` ```

14
src/core/ModelUtils.ts

@ -14,6 +14,8 @@ import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import { Line2 } from 'three/examples/jsm/lines/Line2' import { Line2 } from 'three/examples/jsm/lines/Line2'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry' import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'
import LineSegmentManager from '@/core/manager/LineSegmentManager.ts' import LineSegmentManager from '@/core/manager/LineSegmentManager.ts'
import type InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
import { MeshWrap } from '@/core/manager/InstanceMeshManager.ts'
/** /**
* 2D * 2D
@ -697,6 +699,18 @@ export function getAABBox(matrix: THREE.Matrix4 | ItemJson): THREE.Vector3[] {
return edgePositions return edgePositions
} }
export function drawShadowBox(id: string, meshManager: InstanceMeshManager, matrix: THREE.Matrix4 | ItemJson, userData: any = {}): MeshWrap {
if (!(matrix instanceof THREE.Matrix4)) {
// 从 tf 读取的模型, 需要调整Y轴以使底面位于Y=0
matrix = getMatrixFromTf(matrix.tf)
}
const wrap = meshManager.create(id, userData)
wrap.setMatrix4(matrix)
return wrap
}
export function drawOBBoxUseLineManager(lineId: string, lineManager: LineSegmentManager, matrix: THREE.Matrix4 | ItemJson, padding: number = 0) { export function drawOBBoxUseLineManager(lineId: string, lineManager: LineSegmentManager, matrix: THREE.Matrix4 | ItemJson, padding: number = 0) {
// 定义单位立方体的边对应的顶点索引 // 定义单位立方体的边对应的顶点索引
const edges = [ const edges = [

3
src/core/base/BaseInteraction.ts

@ -322,9 +322,6 @@ export default abstract class BaseInteraction {
}) })
} }
// 把点加入拖拽控制器
// this.viewport.dragControl.setDragObjects(marker, 'push')
// 更新起始点为新添加的点 // 更新起始点为新添加的点
this.linkStartPointId = catchPoint.id this.linkStartPointId = catchPoint.id
this.linkStartPointObject = this.viewport.entityManager.findObjectById(catchPoint.id) this.linkStartPointObject = this.viewport.entityManager.findObjectById(catchPoint.id)

1
src/core/base/BaseRenderer.ts

@ -2,7 +2,6 @@ import type Viewport from '@/core/engine/Viewport'
import * as THREE from 'three' import * as THREE from 'three'
import { getLineId, getMatrixFromTf, setUserDataForItem, setUserDataForLine } from '@/core/ModelUtils.ts' import { getLineId, getMatrixFromTf, setUserDataForItem, setUserDataForLine } from '@/core/ModelUtils.ts'
import { Line2 } from 'three/examples/jsm/lines/Line2' import { Line2 } from 'three/examples/jsm/lines/Line2'
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import { LineWrap } from '@/core/manager/LineSegmentManager.ts' import { LineWrap } from '@/core/manager/LineSegmentManager.ts'
import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts' import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts'
import { MeshWrap } from '@/core/manager/InstanceMeshManager.ts' import { MeshWrap } from '@/core/manager/InstanceMeshManager.ts'

3
src/core/engine/Viewport.ts

@ -36,7 +36,6 @@ export default class Viewport {
statsControls: Stats statsControls: Stats
controls: OrbitControls controls: OrbitControls
raycaster: THREE.Raycaster raycaster: THREE.Raycaster
// dragControl: any // EsDragControls
animationFrameId: any = null animationFrameId: any = null
scene: SceneHelp scene: SceneHelp
@ -64,7 +63,7 @@ export default class Viewport {
// 对象实例管理器 moduleName -> InstanceMeshManager // 对象实例管理器 moduleName -> InstanceMeshManager
meshManager: Map<string, InstanceMeshManager> = new Map() meshManager: Map<string, InstanceMeshManager> = new Map()
// 线段实例管理器 moduleName -> InstancePointManager // 线段实例管理器 moduleName -> LineSegmentManager
lineSegmentManagerMap: Map<string, LineSegmentManager> = new Map() lineSegmentManagerMap: Map<string, LineSegmentManager> = new Map()
// 监听窗口大小变化 // 监听窗口大小变化

98
src/core/manager/DragManager.ts

@ -1,25 +1,25 @@
import * as THREE from 'three' import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport.ts' import type Viewport from '@/core/engine/Viewport.ts'
import { getClosestObject } from '@/core/ModelUtils.ts' import { drawShadowBox, getClosestObject } from '@/core/ModelUtils.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts' import type { Object3DLike } from '@/types/ModelTypes.ts'
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import Constract from '@/core/Constract.ts' import Constract from '@/core/Constract.ts'
import InstanceMeshManager, { MeshWrap } from '@/core/manager/InstanceMeshManager.ts'
/** /**
* ThreeJS X/Z * ThreeJS X/Z
*/ */
export default class DragControl { export default class DragManager {
private viewport: Viewport private viewport: Viewport
private _is_enabled: boolean = true private _is_enabled: boolean = true
private domElement: HTMLElement private domElement: HTMLElement
private isPointerDown: boolean = false private isPointerDown: boolean = false
private dragStartMouse: THREE.Vector2 = new THREE.Vector2() private dragStartMouse: THREE.Vector2 = new THREE.Vector2()
private dragShadows: MeshWrap[] = []
private checkStateInterval: number | null = null private checkStateInterval: number | null = null
private dragShadowsGroup: THREE.Group | null = null
private dragDelayTimeout: number | null = null private dragDelayTimeout: number | null = null
private readonly SHADOW_GEOMETRY = new THREE.BoxGeometry(1, 1, 1)
private static readonly SHADOW_MATERIAL = new THREE.MeshBasicMaterial({ private readonly SHADOW_MATERIAL = new THREE.MeshBasicMaterial({
color: 0x222222, color: 0x222222,
transparent: true, transparent: true,
opacity: 0.5, opacity: 0.5,
@ -80,6 +80,7 @@ export default class DragControl {
let selectedObjects = [intersected] let selectedObjects = [intersected]
const multiSelected = this.viewport.state.multiSelectedObjects const multiSelected = this.viewport.state.multiSelectedObjects
if (multiSelected.length > 0 && multiSelected.includes(intersected)) { if (multiSelected.length > 0 && multiSelected.includes(intersected)) {
// 如果拖拽对象,是红选的,所有红选对象都拖拽
selectedObjects = multiSelected selectedObjects = multiSelected
} }
@ -101,7 +102,7 @@ export default class DragControl {
private onPointerMove = (event: PointerEvent): void => { private onPointerMove = (event: PointerEvent): void => {
if (!this.enabled || !this.domElement) return if (!this.enabled || !this.domElement) return
if (!isNaN(this.dragStartMouse.x) && !isNaN(this.dragStartMouse.y) && this.dragShadowsGroup) { if (!isNaN(this.dragStartMouse.x) && !isNaN(this.dragStartMouse.y)) {
this.isDragging = true this.isDragging = true
this.domElement.style.cursor = 'grabbing' this.domElement.style.cursor = 'grabbing'
this.updateShadows(new THREE.Vector2(CurrentMouseInfo.x, CurrentMouseInfo.z)) this.updateShadows(new THREE.Vector2(CurrentMouseInfo.x, CurrentMouseInfo.z))
@ -195,78 +196,93 @@ export default class DragControl {
private createShadows(objects: Object3DLike[]): void { private createShadows(objects: Object3DLike[]): void {
this.removeShadows() this.removeShadows()
this.dragShadowsGroup = new THREE.Group() const dragShadows = []
for (const obj of objects) { for (const obj of objects) {
if (_.isNil(_.get(obj, 'userData.entityId'))) { const entityId = _.get(obj, 'userData.entityId')
if (_.isNil(entityId)) {
console.error(`Object ${obj.name} missing entityId`) console.error(`Object ${obj.name} missing entityId`)
continue continue
} }
const item = this.viewport.stateManager.findItemById(entityId)
// 克隆对象的几何体和材质 if (!item) {
// const shadowBox = obj.clone() console.error(`Item with entityId ${entityId} not found in stateManager`)
let box: THREE.Box3 continue
if (obj instanceof THREE.Object3D) {
box = new THREE.Box3().setFromObject(obj)
} else if (obj instanceof PointManageWrap) {
box = obj.createBox3()
} }
const size = new THREE.Vector3()
box.getSize(size)
const geometry = new THREE.PlaneGeometry(size.x, size.z)
const shadowBox = new THREE.Mesh(geometry, DragControl.SHADOW_MATERIAL)
shadowBox.position.copy(obj.position)
shadowBox.rotation.x = -Math.PI / 2
shadowBox.userData = { const wrap = drawShadowBox(item.id, this.shadowBoxManager, item, {
isShadow: true, isShadow: true,
entityId: obj.userData.entityId, entityId: obj.userData.entityId,
originPosition: obj.position.clone() // 保存原始位置 originPosition: obj.position.clone() // 保存原始位置
} })
this.dragShadowsGroup.add(shadowBox) dragShadows.push(wrap)
}
this.viewport.scene.add(this.dragShadowsGroup) // let box: THREE.Box3
// if (obj instanceof THREE.Object3D) {
// box = new THREE.Box3().setFromObject(obj)
// } else if (obj instanceof PointManageWrap) {
// box = obj.createBox3()
// }
// const size = new THREE.Vector3()
// box.getSize(size)
// const geometry = new THREE.PlaneGeometry(size.x, size.z)
// const shadowBox = new THREE.Mesh(geometry, DragManager.SHADOW_MATERIAL)
// shadowBox.position.copy(obj.position)
// shadowBox.rotation.x = -Math.PI / 2
//
// shadowBox.userData = {
// isShadow: true,
// entityId: obj.userData.entityId,
// originPosition: obj.position.clone() // 保存原始位置
// }
}
this.dragShadows = dragShadows
}
get shadowBoxManager(): InstanceMeshManager {
const name = 'shadowBoxManager'
return this.viewport.getOrCreateMeshManager(name, () =>
new InstanceMeshManager(name, this.viewport, this.SHADOW_GEOMETRY, this.SHADOW_MATERIAL, false, false, 50)
)
} }
/** /**
* *
*/ */
private removeShadows(): void { private removeShadows(): void {
if (this.dragShadowsGroup) { this.shadowBoxManager.clear()
console.log('removeShadows') this.dragShadows = null
this.viewport.scene.remove(this.dragShadowsGroup)
this.dragShadowsGroup = null
}
} }
/** /**
* X/Z * X/Z
*/ */
private updateShadows(newPosition: THREE.Vector2): void { private updateShadows(newPosition: THREE.Vector2): void {
if (!this.dragShadowsGroup) return if (!this.dragShadows) return
// 计算新位置与拖拽开始位置的偏移量 // 计算新位置与拖拽开始位置的偏移量
const offsetX = newPosition.x - this.dragStartMouse.x const offsetX = newPosition.x - this.dragStartMouse.x
const offsetZ = newPosition.y - this.dragStartMouse.y const offsetZ = newPosition.y - this.dragStartMouse.y
for (let i = 0; i < this.dragShadowsGroup.children.length; i++) { for (let i = 0; i < this.dragShadows.length; i++) {
const shadow = this.dragShadowsGroup.children[i] as THREE.Mesh const shadow = this.dragShadows[i]
if (!shadow.userData.originPosition) { if (!shadow.userData.originPosition) {
console.error(`Shadow ${shadow.name} does not have originPosition`) console.error(`Shadow ${shadow.name} does not have originPosition`)
continue continue
} }
const newPosX = shadow.userData.originPosition.x + offsetX const newPosX = shadow.userData.originPosition.x + offsetX
const newPosY = shadow.userData.originPosition.y
const newPosZ = shadow.userData.originPosition.z + offsetZ const newPosZ = shadow.userData.originPosition.z + offsetZ
shadow.position.set(newPosX, shadow.userData.originPosition.y, newPosZ) // 锁定 Y 轴高度
// console.log(`Updating shadow ${shadow.name} position with offset:`, offsetX, offsetZ) shadow.setMatrix4(new THREE.Matrix4().makeTranslation(newPosX, newPosY, newPosZ))
} }
} }
private dragComplete = (startPos: THREE.Vector2, targetPos: THREE.Vector2): void => { private dragComplete = (startPos: THREE.Vector2, targetPos: THREE.Vector2): void => {
// console.log(`Drag completed from ${startPos.toArray()} to ${targetPos.toArray()}`)
this.viewport.stateManager.update(({ getEntity, putEntity, deleteEntity, addEntity }) => { this.viewport.stateManager.update(({ getEntity, putEntity, deleteEntity, addEntity }) => {
for (const object of this.dragShadowsGroup.children) { for (const object of this.dragShadows) {
const entityId = object.userData.entityId const entityId = object.userData.entityId
if (entityId) { if (entityId) {
const entity = getEntity(entityId) const entity = getEntity(entityId)

13
src/core/manager/InstanceMeshManager.ts

@ -1,8 +1,6 @@
import * as THREE from 'three' import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport.ts' import type Viewport from '@/core/engine/Viewport.ts'
import InstanceMeshBlock from '@/core/manager/InstanceMeshBlock.ts' import InstanceMeshBlock from '@/core/manager/InstanceMeshBlock.ts'
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import { Matrix4 } from 'three/src/math/Matrix4'
export default class InstanceMeshManager { export default class InstanceMeshManager {
private __uuidMap = new Map<string, MeshWrap>() private __uuidMap = new Map<string, MeshWrap>()
@ -36,7 +34,7 @@ export default class InstanceMeshManager {
*/ */
findByMeshInstanceId(blockIndex: number, instanceId: number): MeshWrap { findByMeshInstanceId(blockIndex: number, instanceId: number): MeshWrap {
if (!this.blocks[blockIndex]) { if (!this.blocks[blockIndex]) {
console.error('InstancePointManager: Invalid blockIndex', blockIndex) console.error('InstanceMeshManager: Invalid blockIndex', blockIndex)
return null return null
} }
const uuid = this.blocks[blockIndex].__indexIdMap.get(instanceId) const uuid = this.blocks[blockIndex].__indexIdMap.get(instanceId)
@ -79,7 +77,7 @@ export default class InstanceMeshManager {
blockIndex = block.blockIndex blockIndex = block.blockIndex
} }
if (meshIndex < 0) { if (meshIndex < 0) {
system.showErrorDialog('InstancePointManager: No free index available after creating new block') system.showErrorDialog('InstanceMeshManager: No free index available after creating new block')
return null return null
} }
@ -154,6 +152,13 @@ export default class InstanceMeshManager {
this.geometry?.dispose() // 释放几何体资源 this.geometry?.dispose() // 释放几何体资源
this.material?.dispose() // 释放材质资源 this.material?.dispose() // 释放材质资源
} }
clear() {
for (const block of this.blocks) {
block.dispose()
}
this.__uuidMap.clear()
}
} }
export class MeshWrap { export class MeshWrap {

408
src/core/manager/InstancePointManager.ts

@ -1,408 +0,0 @@
import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport.ts'
import { Vector3 } from 'three/src/math/Vector3'
import InstanceMeshBlock from '@/core/manager/InstanceMeshBlock.ts'
import { getMatrixFromTf } from '@/core/ModelUtils.ts'
/**
*
* 使 InstanceMesh
*/
export default class InstancePointManager {
public readonly name: string
public readonly viewport: Viewport
public readonly allowSelect: boolean
public readonly allowDrag: boolean
public readonly blockCapacity: number = 1000 // 每个 block 的容量
public readonly blocks: InstanceMeshBlock[] = []
private readonly geometry: THREE.BufferGeometry
private readonly material: THREE.Material
private readonly dummy: THREE.Object3D = new THREE.Object3D()
// itemId -> data
private __uuidMap = new Map<string, PointManageWrap>()
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
* @returns ID (-1)
*/
createPoint(item: ItemJson): PointManageWrap {
// Try existing blocks
let meshIndex = -1
let blockIndex = -1
for (const block of this.blocks) {
meshIndex = block.getFreeMeshIndex()
if (meshIndex >= 0) {
blockIndex = block.blockIndex
break
}
}
// 所有 block 都没有空闲索引,创建新的 block
if (meshIndex < 0) {
const block = this.createBlock()
meshIndex = block.getFreeMeshIndex()
blockIndex = block.blockIndex
}
if (meshIndex < 0) {
system.showErrorDialog('InstancePointManager: No free index available after creating new block')
return null
}
return new PointManageWrap(this, blockIndex, meshIndex, {
uuid: item.id,
name: item.name,
blockIndex: blockIndex,
meshIndex: meshIndex,
visible: item.v !== false,
//@ts-ignore
userData: {
t: item.t,
createType: 'point',
blockIndex: blockIndex,
meshIndex: meshIndex,
entityId: item.id
}
})
}
/**
*
* @param item
* @param option
*/
updatePoint(item: ItemJson, option: { position?: Vector3, rotation?: Vector3, scale?: Vector3 } = {}): void {
const wrap = this.__uuidMap.get(item.id)
if (wrap === undefined) return
wrap.visible = item.v !== false
wrap.userData.t = item.t
wrap.userData.entityId = item.id
wrap.setMatrix4(getMatrixFromTf(item.tf))
// let [position, rotation, scale] = item.tf
// if (option.position) {
// position = option.position.toArray()
// }
// if (option.rotation) {
// rotation = option.rotation.toArray()
// }
// if (option.scale) {
// scale = option.scale.toArray()
// }
//
// wrap.position.set(position[0], position[1], position[2])
// wrap.rotation.set(
// THREE.MathUtils.degToRad(rotation[0]),
// THREE.MathUtils.degToRad(rotation[1]),
// THREE.MathUtils.degToRad(rotation[2])
// )
// wrap.scale.set(scale[0], scale[1], scale[2])
// this.syncMeshObject3D(wrap)
}
/**
*
*/
getObject3DLike(id: string): PointManageWrap {
return this.__uuidMap.get(id)
}
/**
*
*/
findByMeshInstanceId(blockIndex: number, instanceId: number): PointManageWrap {
if (!this.blocks[blockIndex]) {
console.error('InstancePointManager: Invalid blockIndex', blockIndex)
return null
}
const uuid = this.blocks[blockIndex].__indexIdMap.get(instanceId)
if (!uuid) return
return this.__uuidMap.get(uuid)
}
setBlockMatrixAt(wrap: PointManageWrap, matrix: THREE.Matrix4) {
const block = this.blocks[wrap.blockIndex]
if (!block) {
console.warn(`InstanceMeshManager: Block ${wrap.blockIndex} not found!`)
return
}
if (!block.__indexIdMap.has(wrap.meshIndex)) {
wrap.parent = block.instancedMesh
this.__uuidMap.set(wrap.uuid, wrap)
block.__indexIdMap.set(wrap.meshIndex, wrap.uuid)
}
block.instancedMesh.setMatrixAt(wrap.meshIndex, matrix)
block.instancedMesh.instanceMatrix.needsUpdate = true
}
// syncMeshObject3D(wrap: PointManageWrap) {
// if (wrap.meshIndex < 0) {
// console.error('InstancePointManager: Invalid meshIndex for wrap', wrap)
// return
// }
// if (!wrap.visible) {
// this.dummy.scale.set(0, 0, 0)
// } else {
// this.dummy.position.copy(wrap.position)
// this.dummy.rotation.copy(wrap.rotation)
// this.dummy.scale.copy(wrap.scale)
// }
// this.dummy.updateMatrix()
//
// const block = this.blocks[wrap.blockIndex]
// if (!wrap.parent) {
// wrap.parent = block.instancedMesh
// this.__uuidMap.set(wrap.uuid, wrap)
// block.__indexIdMap.set(wrap.meshIndex, wrap.uuid)
// }
// block.instancedMesh.setMatrixAt(wrap.meshIndex, this.dummy.matrix)
// block.instancedMesh.instanceMatrix.needsUpdate = true
// }
/**
*
* @param id ID
*/
deletePoint(id: string): void {
const wrap = this.__uuidMap.get(id)
if (!wrap) {
console.warn(`InstanceMeshManager: Wrap with id ${id} not found`)
return
}
const block = this.blocks[wrap.blockIndex]
if (!block) {
console.warn(`InstanceMeshManager: Block ${wrap.blockIndex} not found for wrap ${id}`)
return
}
// 隐藏实例
this.dummy.scale.set(0, 0, 0)
this.dummy.updateMatrix()
block.instancedMesh.setMatrixAt(wrap.meshIndex, this.dummy.matrix)
block.instancedMesh.instanceMatrix.needsUpdate = true
// 回收索引
block.freeIndices.push(wrap.meshIndex)
this.__uuidMap.delete(id)
block.__indexIdMap.delete(wrap.meshIndex)
wrap.dispose()
}
public static create(
name: string,
viewport: Viewport,
geometry: THREE.BufferGeometry,
material: THREE.Material,
allowSelect: boolean, allowDrag: boolean
): InstancePointManager {
return new InstancePointManager(name, allowSelect, allowDrag, viewport, geometry, material)
}
private createBlock(): InstanceMeshBlock {
const block = new InstanceMeshBlock(
this.name, this.allowSelect, this.allowDrag, this.viewport,
this.geometry,
this.material, this.blocks.length, this.blockCapacity
)
this.blocks.push(block)
return block
}
private constructor(name: string, allowSelect: boolean, allowDrag: boolean, viewport: Viewport, geometry: THREE.BufferGeometry, material: THREE.Material) {
this.name = name
this.allowSelect = allowSelect
this.allowDrag = allowDrag
this.viewport = viewport
this.geometry = geometry
this.material = material
// 创建第一个 block
this.createBlock()
// this.instancedMesh = new THREE.InstancedMesh(geometry, material, maxInstances)
// this.instancedMesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage)
// this.instancedMesh.name = name
// console.log('InstancePointManager: [' + name + '] created with maxInstances:', maxInstances)
// viewport.scene.add(this.instancedMesh)
// if (allowSelect) {
// this.viewport.entityManager._selectableObjects.push(this.instancedMesh)
// }
// if (allowDrag) {
// this.viewport.entityManager._draggableObjects.push(this.instancedMesh)
// }
// this.instancedMesh.userData.t = name
// this.instancedMesh.userData.entityId = 'InstancePointManager'
//
// this.dummy.scale.set(0, 0, 0)
// for (let i = 0; i < maxInstances; i++) {
// this.dummy.updateMatrix()
// this.instancedMesh.setMatrixAt(i, this.dummy.matrix)
// this.freeIndices.push(i)
// }
//
// this.instancedMesh.instanceMatrix.needsUpdate = true
}
dispose() {
for (const block of this.blocks) {
block.dispose()
}
this.__uuidMap.clear()
this.blocks.length = 0
}
}
export class PointManageWrap {
readonly manager: InstancePointManager
readonly blockIndex: number = -1
readonly meshIndex: number = -1
parent: THREE.Object3D | null = null
uuid: string
name: string
visible: boolean
//@ts-ignore
userData: UserData = {}
updateWorldMatrix() {
}
get type() {
return 'PointManageWrap'
}
get isObject3D() {
return false
}
constructor(pointManager: InstancePointManager, blockIndex: number, meshIndex: number, data: any) {
this.manager = pointManager
this.blockIndex = blockIndex
this.meshIndex = meshIndex
_.extend(this, data)
}
dispose() {
this.manager.deletePoint(this.uuid)
this.parent = null
}
setMatrix4(matrix: THREE.Matrix4): PointManageWrap {
this.manager.setBlockMatrixAt(this, matrix)
return this
}
set matrix(matrix: THREE.Matrix4) {
this.setMatrix4(matrix)
}
get matrix(): THREE.Matrix4 {
const block = this.manager.blocks[this.blockIndex]
const matrix = new THREE.Matrix4()
block.instancedMesh.getMatrixAt(this.meshIndex, matrix)
return matrix
}
applyMatrix4(targetMatrix: THREE.Matrix4): PointManageWrap {
const matrix = this.matrix
const newMatrix = matrix.multiplyMatrices(targetMatrix, matrix)
this.setMatrix4(newMatrix)
return this
}
createBox3() {
const instancedMesh = this.manager.blocks[this.blockIndex]?.instancedMesh
const matrix = new THREE.Matrix4()
instancedMesh.getMatrixAt(this.meshIndex, matrix)
// 创建包围盒并应用矩阵
const geometry = instancedMesh.geometry
//@ts-ignore
const localBox = new THREE.Box3().setFromBufferAttribute(geometry.attributes.position)
return localBox.clone().applyMatrix4(matrix)
}
createBox3Points() {
// 原始代码 =================================
// const instancedMesh = this.manager.blocks[this.blockIndex]?.instancedMesh
//
// const matrix = new THREE.Matrix4()
// instancedMesh.getMatrixAt(this.meshIndex, matrix)
// // 创建包围盒并应用矩阵
// const geometry = instancedMesh.geometry
// //@ts-ignore
// const localBox = new THREE.Box3().setFromBufferAttribute(geometry.attributes.position)
// return localBox.clone().applyMatrix4(matrix)
// =================================
// TF 代码 =================================
const item = this.manager.viewport.entityManager.findItemById(this.uuid)
const [pos, rot, scale] = item.tf
// // item.tf = [[8.5, 0.1, 2], [0, 0, 0], [1.5, 0.1, 2]]
const matrix = new THREE.Matrix4()
matrix.compose(
new THREE.Vector3(pos[0], pos[1], pos[2]),
new THREE.Quaternion().setFromEuler(new THREE.Euler(
THREE.MathUtils.degToRad(rot[0]),
THREE.MathUtils.degToRad(rot[1]),
THREE.MathUtils.degToRad(rot[2]),
'XYZ'
)),
new THREE.Vector3(scale[0], scale[1], scale[2])
)
// 获取 AABB 包围盒 ==========================
// const aabb = new THREE.Box3()
// .setFromCenterAndSize(new THREE.Vector3(0, 0, 0), new THREE.Vector3(1, 1, 1))
// .applyMatrix4(matrix)
// const min = aabb.min
// const max = aabb.max
// return [
// new THREE.Vector3(min.x - Constract.YELLOW_EXPAND_AMOUNT, max.y + Constract.YELLOW_EXPAND_AMOUNT, min.z - Constract.YELLOW_EXPAND_AMOUNT),
// new THREE.Vector3(max.x + Constract.YELLOW_EXPAND_AMOUNT, max.y + Constract.YELLOW_EXPAND_AMOUNT, min.z - Constract.YELLOW_EXPAND_AMOUNT),
// new THREE.Vector3(max.x + Constract.YELLOW_EXPAND_AMOUNT, max.y + Constract.YELLOW_EXPAND_AMOUNT, max.z + Constract.YELLOW_EXPAND_AMOUNT),
// new THREE.Vector3(min.x - Constract.YELLOW_EXPAND_AMOUNT, max.y + Constract.YELLOW_EXPAND_AMOUNT, max.z + Constract.YELLOW_EXPAND_AMOUNT)
// ]
// 获取 OOBB 包围盒
const halfSize = new THREE.Vector3().setFromMatrixScale(matrix).multiplyScalar(0.5)
const vertices = [
new THREE.Vector3(-halfSize.x, -halfSize.y, -halfSize.z),
new THREE.Vector3(halfSize.x, -halfSize.y, -halfSize.z),
new THREE.Vector3(halfSize.x, halfSize.y, -halfSize.z),
new THREE.Vector3(-halfSize.x, halfSize.y, -halfSize.z),
new THREE.Vector3(-halfSize.x, -halfSize.y, halfSize.z),
new THREE.Vector3(halfSize.x, -halfSize.y, halfSize.z),
new THREE.Vector3(halfSize.x, halfSize.y, halfSize.z),
new THREE.Vector3(-halfSize.x, halfSize.y, halfSize.z)
]
// 应用旋转 + 平移到每个顶点
const verticesWorld = vertices.map(v =>
v.clone().applyMatrix4(matrix)
)
return verticesWorld
}
}

5
src/core/manager/SelectManager.ts

@ -1,16 +1,13 @@
import * as THREE from 'three' import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport' import type Viewport from '@/core/engine/Viewport'
import { Line2 } from 'three/examples/jsm/lines/Line2.js' import { Line2 } from 'three/examples/jsm/lines/Line2.js'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js' import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js'
import EventBus from '@/runtime/EventBus' import EventBus from '@/runtime/EventBus'
import { markRaw } from 'vue' import { markRaw } from 'vue'
import { getSetter } from '@/core/manager/ModuleManager.ts' import { getSetter } from '@/core/manager/ModuleManager.ts'
import Constract from '@/core/Constract.ts' import Constract from '@/core/Constract.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts' import type { Object3DLike } from '@/types/ModelTypes.ts'
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts' import { drawOBBox, drawOBBoxUseLineManager } from '@/core/ModelUtils.ts'
import { drawOBBox, drawOBBoxUseLineManager, getAABBox, getOBBox } from '@/core/ModelUtils.ts'
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
import LineSegmentManager from '@/core/manager/LineSegmentManager.ts' import LineSegmentManager from '@/core/manager/LineSegmentManager.ts'
/** /**

4
src/core/manager/StateManager.ts

@ -498,8 +498,8 @@ export default class StateManager {
/** /**
* ID * ID
*/ */
findItemById(linkStartPointId: string): ItemJson | undefined { findItemById(entityId: string): ItemJson | undefined {
return getFreezeDeep(_.find(this.___vdata.items, item => item.id === linkStartPointId)) return getFreezeDeep(_.find(this.___vdata.items, item => item.id === entityId))
} }
/** /**

3
src/modules/pallet/PalletRenderer.ts

@ -1,11 +1,10 @@
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 Constract from '@/core/Constract.ts' import Constract from '@/core/Constract.ts'
import InstancePointManager from '@/core/manager/InstancePointManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts' import type { Object3DLike } from '@/types/ModelTypes.ts'
import MODULE_GLB_File from '@/assets/Models/Pallet.glb?url' import MODULE_GLB_File from '@/assets/Models/Pallet.glb?url'
import MODULE_3DS_TEX from '@/assets/Models/Pallet.jpg?url' import MODULE_3DS_TEX from '@/assets/Models/Pallet.jpg?url'
import { load3DModule, loadByUrl, loadGlbModule, loadTexture, processModel } from '@/core/ModelUtils.ts' import { loadGlbModule, loadTexture, processModel } from '@/core/ModelUtils.ts'
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts' import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
/** /**

1
src/modules/tote/ToteRenderer.ts

@ -1,7 +1,6 @@
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 Constract from '@/core/Constract.ts' import Constract from '@/core/Constract.ts'
import InstancePointManager from '@/core/manager/InstancePointManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts' import type { Object3DLike } from '@/types/ModelTypes.ts'
import MODULE_3DS_File from '@/assets/Models/Tote.3ds?url' import MODULE_3DS_File from '@/assets/Models/Tote.3ds?url'
import MODULE_3DS_TEX from '@/assets/Models/ToteTex.png?url' import MODULE_3DS_TEX from '@/assets/Models/ToteTex.png?url'

1
src/modules/way/WayRenderer.ts

@ -3,7 +3,6 @@ import BaseRenderer from '@/core/base/BaseRenderer.ts'
import MoveLinePointPng from '@/assets/images/moveline_point.png' import MoveLinePointPng from '@/assets/images/moveline_point.png'
import { createLinkPlaneMatrix4, getCargoLineId, getLinkDirection, getMatrixFromTf } from '@/core/ModelUtils.ts' import { createLinkPlaneMatrix4, getCargoLineId, getLinkDirection, getMatrixFromTf } from '@/core/ModelUtils.ts'
import Constract from '@/core/Constract.ts' import Constract from '@/core/Constract.ts'
import InstancePointManager 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 TriangleUrl from '@/assets/images/conveyor/shapes/triangle.png'
import Triangle2Url from '@/assets/images/conveyor/shapes/triangle-double.png' import Triangle2Url from '@/assets/images/conveyor/shapes/triangle-double.png'

Loading…
Cancel
Save