You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
6.3 KiB
207 lines
6.3 KiB
import * as THREE from 'three'
|
|
import BaseRenderer from '@/core/base/BaseRenderer.ts'
|
|
import { decimalSumBy } from '@/core/ModelUtils'
|
|
import Constract from '@/core/Constract.ts'
|
|
import type Viewport from '@/core/engine/Viewport.ts'
|
|
import Rack3dObject from '@/modules/rack/Rack3dObject'
|
|
|
|
/**
|
|
* 货架货位渲染器
|
|
*/
|
|
export default class RackRenderer extends BaseRenderer {
|
|
static POINT_NAME = 'rack'
|
|
|
|
pointMaterial: THREE.Material
|
|
|
|
/**
|
|
* 默认点的高度, 防止和地面重合
|
|
*/
|
|
readonly defulePositionY: number = Constract.HEIGHT_WAY
|
|
readonly defaultScale: THREE.Vector3 = new THREE.Vector3(1, 1, 1)
|
|
readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0)
|
|
readonly defaultLineWidth: number = 0.05
|
|
|
|
constructor(itemTypeName: string) {
|
|
super(itemTypeName)
|
|
}
|
|
|
|
/**
|
|
* 所有的点,必须使用 storeWidth/storeDepth, 改TF无效
|
|
*/
|
|
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(_.sumBy(item.dt.bays, b=>b.bayWidth), this.defaultScale.y, item.dt.rackDepth)
|
|
point.rotation.set(
|
|
THREE.MathUtils.degToRad(item.tf[1][0]),
|
|
THREE.MathUtils.degToRad(item.tf[1][1]),
|
|
THREE.MathUtils.degToRad(item.tf[1][2])
|
|
)
|
|
}
|
|
|
|
createLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) {
|
|
// throw new Error('not allow store line.')
|
|
}
|
|
|
|
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType) {
|
|
// throw new Error('not allow store line.')
|
|
}
|
|
|
|
updateLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) {
|
|
// throw new Error('not allow store line.')
|
|
}
|
|
|
|
/**
|
|
* 获取物品存放在货架后的位置和旋转角度
|
|
* item.dt.storeAt 必须存在, 比如 { item:'货架ID', bay:0, level:1, cell:0 }
|
|
*/
|
|
getStorePlacement(rack: ItemJson, bay = 0, level = 0, cell = 0): { position: [number, number, number], rotation: [number, number, number] } {
|
|
// if (!item.dt?.storeAt?.item) {
|
|
// // 没有定义存储位置,返回空对象
|
|
// //@ts-ignore
|
|
// return {}
|
|
// }
|
|
//
|
|
// const bay = item.dt?.storeAt?.bay || 0
|
|
// const level = item.dt?.storeAt?.level || 0
|
|
// 暂时不用算格子 const cell = item.dt?.storeAt?.cell || 0
|
|
|
|
// 目标货架
|
|
// const rack = viewport.stateManager.findItemById(item.dt.storeAt.item)
|
|
const rackWidth = decimalSumBy(rack.dt.bays, (b: any) => b.bayWidth)
|
|
const bays = rack.dt.bays
|
|
const levelHeights = rack.dt.bays[bay]?.levelHeight
|
|
|
|
// 局部坐标系下的偏移量
|
|
let localX = 0
|
|
for (let i = 0; i < bay; i++) {
|
|
localX += bays[i]?.bayWidth || 0
|
|
}
|
|
localX += bays[bay].bayWidth / 2 // 居中
|
|
|
|
let localY = 0
|
|
for (let i = 0; i <= level; i++) {
|
|
localY += levelHeights[i]
|
|
}
|
|
|
|
// 构建局部偏移向量
|
|
const rackPos = new THREE.Vector3(...rack.tf[0])
|
|
const offset = new THREE.Vector3(
|
|
localX - rackWidth / 2, // 相对坐标从最左边开始,
|
|
localY, 0)
|
|
|
|
// 应用货架的旋转
|
|
const q = new THREE.Quaternion()
|
|
q.setFromEuler(new THREE.Euler(
|
|
THREE.MathUtils.degToRad(rack.tf[1][0]),
|
|
THREE.MathUtils.degToRad(rack.tf[1][1]),
|
|
THREE.MathUtils.degToRad(rack.tf[1][2])
|
|
))
|
|
|
|
offset.applyQuaternion(q)
|
|
const worldPosition = rackPos.clone().add(offset)
|
|
|
|
return {
|
|
position: [
|
|
worldPosition.x,
|
|
worldPosition.y + rack.dt.bottomBarHeight + 0.05, // 加上横梁高度
|
|
worldPosition.z
|
|
],
|
|
rotation: [
|
|
// 托盘旋转90度才能放进货架
|
|
rack.tf[1][0],
|
|
rack.tf[1][1] + 90,
|
|
rack.tf[1][2]
|
|
]
|
|
}
|
|
}
|
|
|
|
updatePoint(item: ItemJson, group: THREE.Group, option?: RendererCudOption): THREE.Group {
|
|
group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
|
|
group.rotation.set(
|
|
THREE.MathUtils.degToRad(item.tf[1][0]),
|
|
THREE.MathUtils.degToRad(item.tf[1][1]),
|
|
THREE.MathUtils.degToRad(item.tf[1][2])
|
|
)
|
|
// group.scale 不允许修改!!
|
|
|
|
// 禁止缩放,
|
|
item.tf[2][0] = item.dt.rackWidth
|
|
item.tf[2][1] = item.dt.rackHeight
|
|
|
|
|
|
// 更新放在内部的所有箱子
|
|
const subItems = this.tempViewport.runtimeManager.getItemsByRack(item.id)
|
|
const viewport = this.tempViewport
|
|
|
|
if (subItems) {
|
|
_.defer(() => {
|
|
viewport.stateManager.update(({ getEntity, putEntity, deleteEntity, addEntity }) => {
|
|
for (const subItemId of subItems) {
|
|
const subItem = getEntity(subItemId)
|
|
if (subItem) {
|
|
const { position, rotation } = this.getStorePlacement(item, subItem.dt.storeAt.bay, subItem.dt.storeAt.level, subItem.dt.storeAt.cell)
|
|
if (position) {
|
|
subItem.tf[0][0] = position[0]
|
|
subItem.tf[0][1] = position[1]
|
|
subItem.tf[0][2] = position[2]
|
|
subItem.tf[1][0] = rotation[0]
|
|
subItem.tf[1][1] = rotation[1]
|
|
subItem.tf[1][2] = rotation[2]
|
|
putEntity(subItem)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
})
|
|
}
|
|
|
|
return group
|
|
}
|
|
|
|
createPoint(item: ItemJson, option?: RendererCudOption): THREE.Object3D {
|
|
// 创建平面几何体
|
|
if (!item.dt.bays || !item.dt.rackDepth) {
|
|
system.showErrorDialog('RackRenderer field bays / rackDepth is null!')
|
|
return null
|
|
}
|
|
|
|
const group = new Rack3dObject(item, option)
|
|
group.name = RackRenderer.POINT_NAME
|
|
|
|
const rackWidth = decimalSumBy(item.dt.bays, (b: any) => b.bayWidth)
|
|
const heights = []
|
|
for (let i = 0; i < item.dt.bays.length; i++) {
|
|
const bay = item.dt.bays[i]
|
|
const bayHeight = decimalSumBy(bay.levelHeight)
|
|
heights.push(bayHeight)
|
|
}
|
|
const rackHeight = _.max(heights)
|
|
|
|
// 设置位置
|
|
group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
|
|
|
|
group.rotation.set(
|
|
THREE.MathUtils.degToRad(item.tf[1][0]),
|
|
THREE.MathUtils.degToRad(item.tf[1][1]),
|
|
THREE.MathUtils.degToRad(item.tf[1][2])
|
|
)
|
|
|
|
item.dt.rackWidth = rackWidth
|
|
item.dt.rackHeight = rackHeight
|
|
|
|
item.tf[2][0] = item.dt.rackWidth
|
|
item.tf[2][1] = item.dt.rackHeight
|
|
|
|
return group
|
|
}
|
|
|
|
dispose() {
|
|
super.dispose()
|
|
this.pointMaterial?.dispose()
|
|
}
|
|
}
|
|
|