32 changed files with 437 additions and 1033 deletions
@ -0,0 +1,67 @@ |
|||
import { Request } from '@ease-forge/shared' |
|||
|
|||
/** |
|||
* 运行管理器 |
|||
*/ |
|||
class RunManager { |
|||
|
|||
// 是否正在运行
|
|||
isRunning: boolean = false |
|||
|
|||
/** |
|||
* 获取所有运行环境 |
|||
*/ |
|||
async getAllEnv(worldId: string): Promise<ServerResponse<EnvInfo[]>> { |
|||
// system.invokeServer('')
|
|||
if (!worldId) { |
|||
return Promise.resolve({ success: true, data: [], msg: '' }) |
|||
} |
|||
const res = await Request.request.post('/api/workbench/EnvController@getAllEnv', { |
|||
worldId: worldId |
|||
}) |
|||
for (const env of res.data) { |
|||
// payload 转换为 json 数据
|
|||
if (env.env_payload) { |
|||
try { |
|||
env.env_payload = JSON.parse(env.env_payload) |
|||
} catch (e) { |
|||
console.error('解析环境负载失败:', e) |
|||
env.env_payload = {} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return res |
|||
} |
|||
|
|||
/** |
|||
* 创建运行环境 |
|||
* @param worldId 世界ID |
|||
* @param envName 运行环境名称 |
|||
* @param isVirtual 是否是虚拟环境 |
|||
*/ |
|||
async createEnv(worldId: string, envName: string, isVirtual: boolean) { |
|||
throw new Error('Method not implemented.') |
|||
} |
|||
|
|||
/** |
|||
* 开始运行 |
|||
*/ |
|||
async run(timeRate: number, envId: number) { |
|||
if (this.isRunning) { |
|||
await this.stop() |
|||
} |
|||
|
|||
// 启动 websocket 监听等等
|
|||
} |
|||
|
|||
/** |
|||
* 停止运行 |
|||
*/ |
|||
async stop() { |
|||
// 停止 websocket 监听等等
|
|||
} |
|||
} |
|||
|
|||
const runManager = new RunManager() |
|||
export default runManager |
|||
@ -1,13 +1,12 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import CartonRenderer from './CartonRenderer.ts' |
|||
import CartonInteraction from './CartonInteraction.ts' |
|||
import propertySetter from "./CartonPropertySetter.ts"; |
|||
import propertySetter from './CartonPropertySetter.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'carton' |
|||
|
|||
export default defineModule({ |
|||
name: ITEM_TYPE_NAME, |
|||
export default defineModule(ITEM_TYPE_NAME, () => ({ |
|||
renderer: new CartonRenderer(ITEM_TYPE_NAME), |
|||
interaction: new CartonInteraction(ITEM_TYPE_NAME), |
|||
setter: propertySetter, |
|||
}) |
|||
setter: propertySetter |
|||
})) |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import ChargerRenderer from './ChargerRenderer.ts' |
|||
import ChargerInteraction from './ChargerInteraction.ts' |
|||
import propertySetter from "@/modules/charger/ChargerPropertySetter.ts"; |
|||
import propertySetter from '@/modules/charger/ChargerPropertySetter.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'charger' |
|||
|
|||
export default defineModule({ |
|||
name: ITEM_TYPE_NAME, |
|||
export default defineModule(ITEM_TYPE_NAME, () => ({ |
|||
renderer: new ChargerRenderer(ITEM_TYPE_NAME), |
|||
interaction: new ChargerInteraction(ITEM_TYPE_NAME), |
|||
setter: propertySetter, |
|||
}) |
|||
setter: propertySetter |
|||
})) |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import Cl2Renderer from './Cl2Renderer.ts' |
|||
import Cl2Interaction from './Cl2Interaction.ts' |
|||
import propertySetter from "./Cl2PropertySetter.ts"; |
|||
import propertySetter from './Cl2PropertySetter.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'cl2' |
|||
|
|||
export default defineModule({ |
|||
name: ITEM_TYPE_NAME, |
|||
export default defineModule(ITEM_TYPE_NAME, () => ({ |
|||
renderer: new Cl2Renderer(ITEM_TYPE_NAME), |
|||
interaction: new Cl2Interaction(ITEM_TYPE_NAME), |
|||
setter: propertySetter, |
|||
}) |
|||
setter: propertySetter |
|||
})) |
|||
|
|||
@ -1,13 +1,13 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import ClxRenderer from './ClxRenderer.ts' |
|||
import ClxInteraction from './ClxInteraction.ts' |
|||
import propertySetter from "@/modules/clx/ClxPropertySetter.ts"; |
|||
import propertySetter from '@/modules/clx/ClxPropertySetter.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'clx' |
|||
|
|||
export default defineModule({ |
|||
export default defineModule(ITEM_TYPE_NAME, () => ({ |
|||
name: ITEM_TYPE_NAME, |
|||
renderer: new ClxRenderer(ITEM_TYPE_NAME), |
|||
interaction: new ClxInteraction(ITEM_TYPE_NAME), |
|||
setter: propertySetter, |
|||
}) |
|||
setter: propertySetter |
|||
})) |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import GstoreRenderer from './GstoreRenderer.ts' |
|||
import GstoreInteraction from './GstoreInteraction.ts' |
|||
import propertySetter from "@/modules/gstore/GstorePropertySetter.ts"; |
|||
import propertySetter from '@/modules/gstore/GstorePropertySetter.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'gstore' |
|||
|
|||
export default defineModule({ |
|||
name: ITEM_TYPE_NAME, |
|||
export default defineModule(ITEM_TYPE_NAME, () => ({ |
|||
renderer: new GstoreRenderer(ITEM_TYPE_NAME), |
|||
interaction: new GstoreInteraction(ITEM_TYPE_NAME), |
|||
setter: propertySetter, |
|||
}) |
|||
setter: propertySetter |
|||
})) |
|||
|
|||
@ -1,13 +1,14 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import MeasureRenderer from './MeasureRenderer.ts' |
|||
import MeasureInteraction from './MeasureInteraction.ts' |
|||
import propertySetter from "@/modules/measure/MeasurePropertySetter.ts"; |
|||
import propertySetter from '@/modules/measure/MeasurePropertySetter.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'measure' |
|||
|
|||
export default defineModule({ |
|||
name: ITEM_TYPE_NAME, |
|||
console.log('MeasureRenderer initialized at', performance.now()) |
|||
|
|||
export default defineModule(ITEM_TYPE_NAME, () => ({ |
|||
renderer: new MeasureRenderer(ITEM_TYPE_NAME), |
|||
interaction: new MeasureInteraction(ITEM_TYPE_NAME), |
|||
setter: propertySetter, |
|||
}) |
|||
setter: propertySetter |
|||
})) |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import PalletRenderer from './PalletRenderer.ts' |
|||
import PalletInteraction from './PalletInteraction.ts' |
|||
import propertySetter from "@/modules/pallet/PalletPropertySetter.ts"; |
|||
import propertySetter from '@/modules/pallet/PalletPropertySetter.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'pallet' |
|||
|
|||
export default defineModule({ |
|||
name: ITEM_TYPE_NAME, |
|||
export default defineModule(ITEM_TYPE_NAME, () => ({ |
|||
renderer: new PalletRenderer(ITEM_TYPE_NAME), |
|||
interaction: new PalletInteraction(ITEM_TYPE_NAME), |
|||
setter: propertySetter, |
|||
}) |
|||
setter: propertySetter |
|||
})) |
|||
|
|||
@ -1,760 +0,0 @@ |
|||
import * as THREE from 'three' |
|||
import { BufferGeometry } from 'three' |
|||
import BaseRenderer from '@/core/base/BaseRenderer.ts' |
|||
import { decimalSumBy } from '@/core/ModelUtils' |
|||
import Constract from '@/core/Constract.ts' |
|||
import Plastic_Rough_JPG from '@/assets/Models/Plastic_Rough.jpg?inline' |
|||
import storageBar_PNG from '@/assets/Models/storageBar.png?inline' |
|||
import { Material } from 'three/src/materials/Material' |
|||
import { InstancedMesh } from 'three/src/objects/InstancedMesh' |
|||
//@ts-ignore |
|||
import { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js' |
|||
import type Viewport from '@/core/engine/Viewport.ts' |
|||
import type { Object3DLike } from '@/types/ModelTypes.ts' |
|||
|
|||
/** |
|||
* 货架货位渲染器 |
|||
*/ |
|||
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]) |
|||
) |
|||
} |
|||
|
|||
|
|||
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D { |
|||
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(viewport: Viewport, item: ItemJson): { 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 + this.bottomBarHeight + 0.1, // 加上横梁高度 |
|||
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(viewport, subItem) |
|||
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 THREE.Group() |
|||
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) |
|||
// // 绘制背景矩形框 |
|||
// const planeGeometry = new THREE.PlaneGeometry(rackWidth, item.dt.rackDepth) |
|||
// |
|||
// planeGeometry.rotateX(Math.PI / 2) |
|||
// |
|||
// const planeMaterial = new THREE.MeshBasicMaterial({ |
|||
// color: '#9a9090', |
|||
// transparent: true, // 启用透明 |
|||
// opacity: 0.5, // 50%透明度 |
|||
// depthWrite: false, // 防止深度冲突 |
|||
// side: THREE.DoubleSide // 双面渲染:ml-citation{ref="5,8" data="citationList"} |
|||
// }) |
|||
// const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial) |
|||
// group.add(planeMesh) |
|||
// |
|||
// |
|||
// // 绘制边框 |
|||
// const lineXLen = rackWidth - this.defaultLineWidth |
|||
// const lineYLen = item.dt.rackDepth - this.defaultLineWidth |
|||
// |
|||
// const lineGeometry = new LineGeometry().setPositions([ |
|||
// -(lineXLen / 2), 0, -(lineYLen / 2), |
|||
// lineXLen / 2, 0, -(lineYLen / 2), |
|||
// lineXLen / 2, 0, lineYLen / 2, |
|||
// -(lineXLen / 2), 0, lineYLen / 2, |
|||
// -(lineXLen / 2), 0, -(lineYLen / 2) |
|||
// ]) |
|||
// const lineMaterial = new LineMaterial({ |
|||
// color: '#0d89a5', |
|||
// linewidth: this.defaultLineWidth, |
|||
// worldUnits: true, |
|||
// resolution: new THREE.Vector2(window.innerWidth, window.innerHeight), |
|||
// side: THREE.DoubleSide |
|||
// }) |
|||
// const line = new Line2(lineGeometry, lineMaterial) |
|||
// group.add(line as THREE.Object3D) |
|||
// |
|||
// let lineDistanceX = 0 |
|||
// |
|||
// for (let i = 0; item.dt.bays.length > 1 && i < item.dt.bays.length - 1; i++) { |
|||
// const bay = item.dt.bays[i] |
|||
// lineDistanceX += bay.bayWidth |
|||
// const lineGeometryT = new LineGeometry().setPositions([ |
|||
// -(lineDistanceX) + (lineXLen / 2), 0, lineYLen / 2, |
|||
// -(lineDistanceX) + (lineXLen / 2), 0, -(lineYLen / 2) |
|||
// ]) |
|||
// const lineT = new Line2(lineGeometryT, lineMaterial) |
|||
// group.add(lineT as THREE.Object3D) |
|||
// } |
|||
|
|||
const meshes = this.createRack(item, option) |
|||
|
|||
meshes.forEach(mesh => { |
|||
group.add(mesh) |
|||
mesh.instanceMatrix.needsUpdate = true |
|||
}) |
|||
|
|||
// 设置位置 |
|||
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() |
|||
} |
|||
|
|||
rackVerticalBarWidth = 0.1 |
|||
rackVerticalBarDepth = 0.08 |
|||
rackVerticalBarColor = 0xFF35499C |
|||
rackVerticalBarGeometry: BufferGeometry = null |
|||
rackVerticalBarMaterial: Material = null |
|||
|
|||
rackLinkBarColor = 0xFF35499C |
|||
rackLinkBarGeometry: BufferGeometry = null |
|||
rackLinkBarMaterial: Material = null |
|||
|
|||
rackHorizontalBarWidth = 0.1 |
|||
rackHorizontalBarDepth = 0.08 |
|||
rackHorizontalBarColor = 0xFFF97F27 |
|||
rackHorizontalBarGeometry: BufferGeometry = null |
|||
rackHorizontalBarMaterial: Material = null |
|||
|
|||
bottomBarHeight = 0.2 |
|||
bottomLinkHeight = 0.2 |
|||
|
|||
barSectionPoints = [ |
|||
{ x: -0.05, y: -0.05 }, |
|||
{ x: -0.025, y: -0.05 }, |
|||
{ x: -0.01, y: -0.045 }, |
|||
{ x: 0.01, y: -0.045 }, |
|||
{ x: 0.025, y: -0.05 }, |
|||
{ x: 0.05, y: -0.05 }, |
|||
{ x: 0.05, y: 0.042 }, |
|||
{ x: 0.042, y: 0.05 }, |
|||
{ x: 0.025, y: 0.05 }, |
|||
{ x: 0.025, y: 0.042 }, |
|||
{ x: 0.042, y: 0.042 }, |
|||
{ x: 0.042, y: -0.042 }, |
|||
{ x: -0.042, y: -0.042 }, |
|||
{ x: -0.042, y: 0.042 }, |
|||
{ x: -0.025, y: 0.042 }, |
|||
{ x: -0.025, y: 0.05 }, |
|||
{ x: -0.042, y: 0.05 }, |
|||
{ x: -0.05, y: 0.042 }, |
|||
{ x: -0.05, y: -0.05 } |
|||
] |
|||
|
|||
linkSectionPoints = [ |
|||
{ x: -0.05, y: -0.05 }, |
|||
{ x: -0.05, y: 0.05 }, |
|||
{ x: 0, y: 0.05 }, |
|||
{ x: 0, y: 0.06 }, |
|||
{ x: -0.06, y: 0.06 }, |
|||
{ x: -0.06, y: -0.05 }, |
|||
{ x: -0.05, y: -0.05 } |
|||
] |
|||
|
|||
linkBarSectionPoints = [ |
|||
{ x: -0.025, y: -0.025 }, |
|||
{ x: 0.025, y: -0.025 }, |
|||
{ x: 0.025, y: 0.025 }, |
|||
{ x: -0.025, y: 0.025 }, |
|||
{ x: -0.025, y: -0.025 } |
|||
] |
|||
|
|||
createVerticalBar(x, y, z, length): THREE.BufferGeometry { |
|||
|
|||
// 创建一个形状 柱子的截面形状 |
|||
const shape = new THREE.Shape() |
|||
shape.moveTo(this.barSectionPoints[0].x, this.barSectionPoints[0].y) |
|||
for (let i = 1; i < this.barSectionPoints.length; i++) { |
|||
shape.lineTo(this.barSectionPoints[i].x, this.barSectionPoints[i].y) |
|||
} |
|||
|
|||
// 拉伸轨迹线 |
|||
const curve = new THREE.CatmullRomCurve3( |
|||
[new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, length, 0)], |
|||
false, // 闭合曲线 |
|||
'catmullrom', |
|||
0 |
|||
) |
|||
|
|||
// 挤出几何图形 参数 |
|||
const options = { |
|||
steps: 1, |
|||
bevelEnabled: false, |
|||
extrudePath: curve // 设置挤出轨迹 |
|||
} |
|||
// 创建挤出几何体 |
|||
const geometry = new THREE.ExtrudeGeometry(shape, options) |
|||
// 调整uv方便正确贴图 |
|||
this.resetUVs(geometry) |
|||
return geometry |
|||
} |
|||
|
|||
createVerticalBarMaterial(): THREE.Material { |
|||
|
|||
let textureLoader = new THREE.TextureLoader() |
|||
|
|||
// 加载纹理 |
|||
const textureHole = textureLoader.load(storageBar_PNG) // 孔洞 |
|||
const textureMaterial = textureLoader.load(Plastic_Rough_JPG) // 表面材质 |
|||
|
|||
textureHole.repeat.set(10, 18) // X轴重复,Y轴重复 |
|||
textureMaterial.repeat.set(2, 2) // X轴重复,Y轴重复 |
|||
// textureHole.offset.set(0.5, 0) |
|||
// textureHole.center.set(0.5, 0) |
|||
|
|||
// 必须设置包裹模式为重复 |
|||
textureHole.wrapS = THREE.RepeatWrapping |
|||
textureHole.wrapT = THREE.RepeatWrapping |
|||
textureMaterial.wrapS = THREE.RepeatWrapping |
|||
textureMaterial.wrapT = THREE.RepeatWrapping |
|||
|
|||
const material = new THREE.MeshPhongMaterial() |
|||
material.alphaMap = textureHole |
|||
material.normalMap = textureMaterial |
|||
material.color.setHex(this.rackVerticalBarColor, 'srgb') |
|||
material.specular.setHex(0xff6d6d6d, 'srgb') |
|||
material.transparent = true |
|||
material.needsUpdate = true |
|||
|
|||
return material |
|||
} |
|||
|
|||
createLinkBar(x, y, z, vBarLength, depth, bottomDistance, topDistance): THREE.BufferGeometry { |
|||
|
|||
const bgs: BufferGeometry[] = [] |
|||
const top = vBarLength - topDistance |
|||
// 创建一个形状 柱子的截面形状 |
|||
const shape = new THREE.Shape() |
|||
shape.moveTo(this.linkBarSectionPoints[0].x, this.linkBarSectionPoints[0].y) |
|||
for (let i = 1; i < this.linkBarSectionPoints.length; i++) { |
|||
shape.lineTo(this.linkBarSectionPoints[i].x, this.linkBarSectionPoints[i].y) |
|||
} |
|||
|
|||
// 拉伸轨迹线 横向 底部 |
|||
const curveHBottom = new THREE.CatmullRomCurve3( |
|||
[new THREE.Vector3(0, bottomDistance, 0), new THREE.Vector3(0, bottomDistance, depth)], |
|||
false, // 闭合曲线 |
|||
'catmullrom', |
|||
0 |
|||
) |
|||
|
|||
// 挤出几何图形 参数 |
|||
const optionsHBottom = { |
|||
steps: 1, |
|||
bevelEnabled: false, |
|||
extrudePath: curveHBottom // 设置挤出轨迹 |
|||
} |
|||
|
|||
// 拉伸轨迹线 横向 底部 |
|||
const curveHTop = new THREE.CatmullRomCurve3( |
|||
[new THREE.Vector3(0, top, 0), new THREE.Vector3(0, top, depth)], |
|||
false, // 闭合曲线 |
|||
'catmullrom', |
|||
0 |
|||
) |
|||
|
|||
// 挤出几何图形 参数 |
|||
const optionsHTop = { |
|||
steps: 1, |
|||
bevelEnabled: false, |
|||
extrudePath: curveHTop // 设置挤出轨迹 |
|||
} |
|||
|
|||
// 创建挤出几何体 |
|||
const geometryHBottom = new THREE.ExtrudeGeometry(shape, optionsHBottom) |
|||
const geometryHTop = new THREE.ExtrudeGeometry(shape, optionsHTop) |
|||
bgs.push(geometryHBottom, geometryHTop) |
|||
|
|||
let remainingHeight = vBarLength - bottomDistance - topDistance |
|||
|
|||
// 需要创建斜杆 |
|||
|
|||
for (let i = 0; i < Math.floor(remainingHeight / depth); i++) { |
|||
// 拉伸轨迹线 斜向 |
|||
const curveD = new THREE.CatmullRomCurve3( |
|||
(i % 2 == 0) ? [new THREE.Vector3(0, bottomDistance + depth * i, 0), new THREE.Vector3(0, bottomDistance + depth * (i + 1), depth)] |
|||
: [new THREE.Vector3(0, bottomDistance + depth * (i + 1), 0), new THREE.Vector3(0, bottomDistance + depth * (i), depth)], |
|||
false, // 闭合曲线 |
|||
'catmullrom', |
|||
0 |
|||
) |
|||
|
|||
const optionsD = { |
|||
steps: 1, |
|||
bevelEnabled: false, |
|||
extrudePath: curveD // 设置挤出轨迹 |
|||
} |
|||
|
|||
const geometryD = new THREE.ExtrudeGeometry(shape, optionsD) |
|||
bgs.push(geometryD) |
|||
} |
|||
|
|||
if (vBarLength - bottomDistance - topDistance > depth) { |
|||
|
|||
|
|||
} |
|||
|
|||
// 调整uv方便正确贴图 |
|||
// this.resetUVs(geometry); |
|||
return mergeGeometries(bgs) |
|||
} |
|||
|
|||
createLinkBarMaterial(): THREE.Material { |
|||
|
|||
const material = new THREE.MeshPhongMaterial() |
|||
material.color.setHex(this.rackLinkBarColor, 'srgb') |
|||
material.specular.setHex(0xff6d6d6d, 'srgb') |
|||
material.transparent = true |
|||
material.needsUpdate = true |
|||
|
|||
return material |
|||
} |
|||
|
|||
createHorizontalBar(x, y, z, length): THREE.BufferGeometry { |
|||
|
|||
// 创建一个形状 柱子的截面形状 |
|||
const shape = new THREE.Shape() |
|||
shape.moveTo(this.barSectionPoints[0].x, this.barSectionPoints[0].y) |
|||
for (let i = 1; i < this.barSectionPoints.length; i++) { |
|||
shape.lineTo(this.barSectionPoints[i].x, this.barSectionPoints[i].y) |
|||
} |
|||
|
|||
// 拉伸轨迹线 |
|||
const curve = new THREE.CatmullRomCurve3( |
|||
[new THREE.Vector3(0.05, 0, 0), new THREE.Vector3(length - 0.05, 0, 0)], |
|||
false, // 闭合曲线 |
|||
'catmullrom', |
|||
0 |
|||
) |
|||
|
|||
// 挤出几何图形 参数 |
|||
const options = { |
|||
steps: 1, |
|||
bevelEnabled: false, |
|||
extrudePath: curve // 设置挤出轨迹 |
|||
} |
|||
// 创建挤出几何体 |
|||
const geometry = new THREE.ExtrudeGeometry(shape, options) |
|||
|
|||
const linkShapeL = new THREE.Shape() |
|||
const linkShapeR = new THREE.Shape() |
|||
linkShapeL.moveTo(this.linkSectionPoints[0].x, this.linkSectionPoints[0].y) |
|||
linkShapeR.moveTo(this.linkSectionPoints[0].x + (length), this.linkSectionPoints[0].y) |
|||
for (let i = 1; i < this.linkSectionPoints.length; i++) { |
|||
linkShapeL.lineTo(this.linkSectionPoints[i].x, this.linkSectionPoints[i].y) |
|||
linkShapeR.lineTo(this.linkSectionPoints[i].x + (length), this.linkSectionPoints[i].y) |
|||
} |
|||
|
|||
// 拉伸轨迹线 |
|||
const linkCurve = new THREE.CatmullRomCurve3( |
|||
[new THREE.Vector3(0, 0, -0.08), new THREE.Vector3(0, 0, 0.08)], |
|||
false, // 闭合曲线 |
|||
'catmullrom', |
|||
0 |
|||
) |
|||
|
|||
// 挤出几何图形 参数 |
|||
const linkOptions = { |
|||
steps: 1, |
|||
bevelEnabled: false, |
|||
extrudePath: linkCurve // 设置挤出轨迹 |
|||
} |
|||
// 创建挤出几何体 |
|||
const linkGeometryL = new THREE.ExtrudeGeometry(linkShapeL, linkOptions) |
|||
linkGeometryL.rotateZ(-Math.PI / 2) |
|||
const linkGeometryR = new THREE.ExtrudeGeometry(linkShapeR, linkOptions) |
|||
linkGeometryR.rotateX(-Math.PI) |
|||
linkGeometryR.rotateZ(-Math.PI / 2) |
|||
|
|||
// 调整uv方便正确贴图 |
|||
// this.resetUVs(geometry); |
|||
return mergeGeometries([geometry, linkGeometryL, linkGeometryR]) |
|||
} |
|||
|
|||
createHorizontalBarMaterial(): THREE.Material { |
|||
|
|||
const material = new THREE.MeshPhongMaterial() |
|||
material.color.setHex(this.rackHorizontalBarColor, 'srgb') |
|||
material.specular.setHex(0xff6d6d6d, 'srgb') |
|||
material.transparent = true |
|||
material.needsUpdate = true |
|||
|
|||
return material |
|||
} |
|||
|
|||
createRack(item: ItemJson, option?: RendererCudOption): InstancedMesh[] { |
|||
if (!item.dt.bays || !item.dt.rackDepth) { |
|||
system.showErrorDialog('RackRenderer field bays / rackDepth is null!') |
|||
return null |
|||
} |
|||
|
|||
const rackPoint = { |
|||
x: item.tf[0][0], |
|||
y: item.tf[0][1], |
|||
z: item.tf[0][2] |
|||
} |
|||
|
|||
const rackWidth = decimalSumBy(item.dt.bays, (b: any) => b.bayWidth) |
|||
const rackDepth = item.dt.rackDepth |
|||
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) |
|||
|
|||
// 计算立住坐标点和长度 |
|||
const vBarMatrix: { x: number, y: number, z: number, sx: number, sy: number, sz: number, rx: number, ry: number, rz: number, l: number }[] = [] |
|||
|
|||
// 计算 |
|||
const linkBarMatrix: { x: number, y: number, z: number, sx: number, sy: number, sz: number, rx: number, ry: number, rz: number, l: number }[] = [] |
|||
|
|||
let distanceX = 0, distanceY = 0 |
|||
|
|||
for (let i = -1; i < item.dt.bays.length; i++) { |
|||
if (i >= 0) { |
|||
const bay = item.dt.bays[i] |
|||
distanceX += bay.bayWidth |
|||
} |
|||
vBarMatrix.push({ |
|||
x: distanceX - rackWidth / 2, |
|||
y: 0, |
|||
z: -rackDepth / 2, |
|||
sx: 0.8, |
|||
sy: 1, |
|||
sz: 1, |
|||
rx: 0, |
|||
ry: Math.PI / 2, |
|||
rz: 0, |
|||
l: rackHeight |
|||
}) |
|||
vBarMatrix.push({ |
|||
x: distanceX - rackWidth / 2, |
|||
y: 0, |
|||
z: item.dt.rackDepth - rackDepth / 2, |
|||
sx: 0.8, |
|||
sy: 1, |
|||
sz: 1, |
|||
rx: 0, |
|||
ry: -Math.PI / 2, |
|||
rz: 0, |
|||
l: rackHeight |
|||
}) |
|||
linkBarMatrix.push({ |
|||
x: distanceX - rackWidth / 2, |
|||
y: 0, |
|||
z: i % 2 == 0 ? (item.dt.rackDepth - rackDepth / 2) : -rackDepth / 2, |
|||
sx: 1, |
|||
sy: 1, |
|||
sz: 1, |
|||
rx: 0, |
|||
ry: i % 2 == 0 ? Math.PI : 0, |
|||
rz: 0, |
|||
l: rackHeight |
|||
}) |
|||
} |
|||
|
|||
// 计算横梁数量 |
|||
const hBarMatrix: { x: number, y: number, z: number, sx: number, sy: number, sz: number, rx: number, ry: number, rz: number, l: number }[] = [] |
|||
distanceX = 0 |
|||
for (let i = 0; i < item.dt.bays.length; i++) { |
|||
distanceY = this.bottomBarHeight |
|||
const bay = item.dt.bays[i] |
|||
for (let j = 0; j < bay.levelHeight.length; j++) { |
|||
const levelHeight = bay.levelHeight[j] |
|||
if (distanceY <= 0) { |
|||
continue |
|||
} |
|||
hBarMatrix.push({ |
|||
x: distanceX - rackWidth / 2, |
|||
y: distanceY, |
|||
z: -rackDepth / 2, |
|||
sx: 1, |
|||
sy: 0.8, |
|||
sz: 1, |
|||
rx: Math.PI / 2, |
|||
ry: 0, |
|||
rz: 0, |
|||
l: bay.bayWidth |
|||
}) |
|||
hBarMatrix.push({ |
|||
x: distanceX - rackWidth / 2, |
|||
y: distanceY, |
|||
z: item.dt.rackDepth - rackDepth / 2, |
|||
sx: 1, |
|||
sy: 0.8, |
|||
sz: 1, |
|||
rx: -Math.PI / 2, |
|||
ry: 0, |
|||
rz: 0, |
|||
l: bay.bayWidth |
|||
}) |
|||
distanceY += levelHeight |
|||
} |
|||
distanceX += bay.bayWidth |
|||
} |
|||
|
|||
const meshes: InstancedMesh[] = [] |
|||
|
|||
if (vBarMatrix.length > 0) { |
|||
if (!this.rackVerticalBarGeometry) { |
|||
this.rackVerticalBarGeometry = this.createVerticalBar(vBarMatrix[0].x, vBarMatrix[0].y, vBarMatrix[0].z, vBarMatrix[0].l) |
|||
} |
|||
if (!this.rackVerticalBarMaterial) { |
|||
this.rackVerticalBarMaterial = this.createVerticalBarMaterial() |
|||
} |
|||
const dummy = new THREE.Object3D() |
|||
const vBarMesh = new THREE.InstancedMesh(this.rackVerticalBarGeometry, this.rackVerticalBarMaterial, vBarMatrix.length) |
|||
for (let i = 0; i < vBarMatrix.length; i++) { |
|||
const vp = vBarMatrix[i] |
|||
dummy.position.set(vp.x, vp.y, vp.z) |
|||
dummy.rotation.set(vp.rx, vp.ry, vp.rz) |
|||
dummy.scale.set(vp.sx, vp.sy, vp.sz) |
|||
dummy.updateMatrix() |
|||
vBarMesh.setMatrixAt(i, dummy.matrix) |
|||
} |
|||
meshes.push(vBarMesh) |
|||
} |
|||
|
|||
if (linkBarMatrix.length > 0) { |
|||
if (!this.rackLinkBarGeometry) { |
|||
this.rackLinkBarGeometry = this.createLinkBar(linkBarMatrix[0].x, linkBarMatrix[0].y, linkBarMatrix[0].z, rackHeight, item.dt.rackDepth, this.bottomLinkHeight, 0.2) |
|||
} |
|||
if (!this.rackLinkBarMaterial) { |
|||
this.rackLinkBarMaterial = this.createLinkBarMaterial() |
|||
} |
|||
const dummy = new THREE.Object3D() |
|||
const linkBarMesh = new THREE.InstancedMesh(this.rackLinkBarGeometry, this.rackLinkBarMaterial, linkBarMatrix.length) |
|||
for (let i = 0; i < linkBarMatrix.length; i++) { |
|||
const lp = linkBarMatrix[i] |
|||
dummy.position.set(lp.x, lp.y, lp.z) |
|||
dummy.rotation.set(lp.rx, lp.ry, lp.rz) |
|||
dummy.scale.set(lp.sx, lp.sy, lp.sz) |
|||
dummy.updateMatrix() |
|||
linkBarMesh.setMatrixAt(i, dummy.matrix) |
|||
} |
|||
meshes.push(linkBarMesh) |
|||
} |
|||
|
|||
if (hBarMatrix.length > 0) { |
|||
if (!this.rackHorizontalBarGeometry) { |
|||
this.rackHorizontalBarGeometry = this.createHorizontalBar(hBarMatrix[0].x, hBarMatrix[0].y, hBarMatrix[0].z, hBarMatrix[0].l) |
|||
} |
|||
if (!this.rackHorizontalBarMaterial) { |
|||
this.rackHorizontalBarMaterial = this.createHorizontalBarMaterial() |
|||
} |
|||
const dummy = new THREE.Object3D() |
|||
const hBarMesh = new THREE.InstancedMesh(this.rackHorizontalBarGeometry, this.rackHorizontalBarMaterial, hBarMatrix.length) |
|||
for (let i = 0; i < hBarMatrix.length; i++) { |
|||
const hp = hBarMatrix[i] |
|||
dummy.position.set(hp.x, hp.y, hp.z) |
|||
dummy.rotation.set(hp.rx, hp.ry, hp.rz) |
|||
dummy.scale.set(hp.sx, hp.sy, hp.sz) |
|||
dummy.updateMatrix() |
|||
hBarMesh.setMatrixAt(i, dummy.matrix) |
|||
} |
|||
meshes.push(hBarMesh) |
|||
} |
|||
return meshes |
|||
} |
|||
|
|||
|
|||
resetUVs(geometry: THREE.ExtrudeGeometry) { |
|||
if (geometry == undefined) return |
|||
const pos = geometry.getAttribute('position'), |
|||
nor = geometry.getAttribute('normal'), |
|||
uvs = geometry.getAttribute('uv') |
|||
|
|||
for (let i = 0; i < pos.count; i++) { |
|||
let x = 0, y = 0 |
|||
|
|||
const nx = Math.abs(nor.getX(i)), ny = Math.abs(nor.getY(i)), nz = Math.abs(nor.getZ(i)) |
|||
|
|||
// if facing X |
|||
if (nx >= ny && nx >= nz) { |
|||
x = pos.getZ(i) |
|||
y = pos.getY(i) |
|||
} |
|||
|
|||
// if facing Y |
|||
if (ny >= nx && ny >= nz) { |
|||
x = pos.getX(i) |
|||
y = pos.getZ(i) |
|||
} |
|||
|
|||
// if facing Z |
|||
if (nz >= nx && nz >= ny) { |
|||
x = pos.getX(i) |
|||
y = pos.getY(i) |
|||
} |
|||
uvs.setXY(i, x, y) |
|||
} |
|||
} |
|||
|
|||
} |
|||
@ -1,13 +1,12 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import RackRenderer from './RackRenderer.ts' |
|||
import RackInteraction from './RackInteraction.ts' |
|||
import propertySetter from "@/modules/rack/RackPropertySetter.ts"; |
|||
import propertySetter from '@/modules/rack/RackPropertySetter.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'rack' |
|||
|
|||
export default defineModule({ |
|||
name: ITEM_TYPE_NAME, |
|||
export default defineModule(ITEM_TYPE_NAME, () => ({ |
|||
renderer: new RackRenderer(ITEM_TYPE_NAME), |
|||
interaction: new RackInteraction(ITEM_TYPE_NAME), |
|||
setter: propertySetter, |
|||
}) |
|||
setter: propertySetter |
|||
})) |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import ShuttleRackRenderer from './ShuttleRackRenderer.ts' |
|||
import ShuttleRackInteraction from './ShuttleRackInteraction.ts' |
|||
import propertySetter from "./ShuttleRackPropertySetter.ts"; |
|||
import propertySetter from './ShuttleRackPropertySetter.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'shuttle_rack' |
|||
|
|||
export default defineModule({ |
|||
name: ITEM_TYPE_NAME, |
|||
export default defineModule(ITEM_TYPE_NAME, () => ({ |
|||
renderer: new ShuttleRackRenderer(ITEM_TYPE_NAME), |
|||
interaction: new ShuttleRackInteraction(ITEM_TYPE_NAME), |
|||
setter: propertySetter, |
|||
}) |
|||
setter: propertySetter |
|||
})) |
|||
|
|||
@ -1,13 +1,12 @@ |
|||
import { defineModule } from '@/core/manager/ModuleManager.ts' |
|||
import WayRenderer from './WayRenderer.ts' |
|||
import WayInteraction from './WayInteraction.ts' |
|||
import propertySetter from "@/modules/way/WayPropertySetter.ts"; |
|||
import propertySetter from '@/modules/way/WayPropertySetter.ts' |
|||
|
|||
export const ITEM_TYPE_NAME = 'way' |
|||
|
|||
export default defineModule({ |
|||
name: ITEM_TYPE_NAME, |
|||
export default defineModule(ITEM_TYPE_NAME, () => ({ |
|||
renderer: new WayRenderer(ITEM_TYPE_NAME), |
|||
interaction: new WayInteraction(ITEM_TYPE_NAME), |
|||
setter: propertySetter, |
|||
}) |
|||
setter: propertySetter |
|||
})) |
|||
|
|||
Loading…
Reference in new issue