Browse Source

基本容器符合尺寸容器要求

master
修宁 6 months ago
parent
commit
e60f0f9185
  1. 65
      src/core/ModelUtils.ts
  2. 47
      src/core/base/BaseRenderer.ts
  3. 319
      src/core/controls/DragControl.ts
  4. 83
      src/core/controls/MouseMoveInspect.ts
  5. 441
      src/core/controls/SelectInspect.ts
  6. 10
      src/core/engine/SceneHelp.ts
  7. 42
      src/core/engine/Viewport.ts
  8. 4
      src/core/manager/EntityManager.ts
  9. 18
      src/core/manager/InstanceMeshManager.ts
  10. 117
      src/core/manager/InstancePointManager.ts
  11. 6
      src/core/manager/StateManager.ts
  12. 2
      src/editor/widgets/modeltree/ModeltreeViewJs.js
  13. 2
      src/example/ExampleUtil.js
  14. 76
      src/example/example1.js
  15. 23
      src/modules/carton/CartonEntity.ts
  16. 14
      src/modules/carton/CartonRenderer.ts
  17. 29
      src/modules/pallet/PalletRenderer.ts
  18. 2
      src/types/ModelTypes.ts

65
src/core/ModelUtils.ts

@ -244,7 +244,10 @@ export function getClosestObject(viewport: Viewport, object: THREE.Object3D, ins
if (object.userData && object.userData.t && object.userData.entityId) {
// 找到第一个有效的业务 Object3D
if (object instanceof THREE.InstancedMesh && instanceId >= 0) {
return viewport.pointManagerMap.get(object.userData.t)?.findByMeshInstanceId(object.userData.blockIndex, instanceId)
const manager = viewport.pointManagerMap.get(object.userData.t)
if (manager) {
return manager.findByMeshInstanceId(object.userData.blockIndex, instanceId)
}
}
return object
}
@ -254,6 +257,51 @@ export function getClosestObject(viewport: Viewport, object: THREE.Object3D, ins
}
/**
* 1x1x1
*/
export function processModel(mesh: THREE.Mesh) {
const geometry = mesh.geometry.clone() as THREE.BufferGeometry
// 获取原始包围盒
//@ts-ignore
const box = new THREE.Box3().setFromBufferAttribute(geometry.attributes.position)
const size = new THREE.Vector3()
box.getSize(size)
// 计算缩放因子:让整个包围盒变成 1x1x1 的立方体
const scaleX = 1 / size.x
const scaleY = 1 / size.y
const scaleZ = 1 / size.z
// 缩放几何体到 1x1x1 立方体(保持原点不变)
geometry.scale(scaleX, scaleY, scaleZ)
// 更新包围盒
//@ts-ignore
const scaledBox = new THREE.Box3().setFromBufferAttribute(geometry.attributes.position)
const center = new THREE.Vector3()
scaledBox.getCenter(center)
// 平移:让中心在 (0, height/2, 0),底部贴地
const translate = new THREE.Matrix4().makeTranslation(
-center.x,
-scaledBox.min.y, // 保证底部贴地
-center.z
)
geometry.applyMatrix4(translate)
// 可选:验证最终包围盒
//@ts-ignore
// const finalBox = new THREE.Box3().setFromBufferAttribute(geometry.attributes.position)
// const finalSize = new THREE.Vector3()
// finalBox.getSize(finalSize)
// console.log('最终包围盒大小:', finalSize) // 应该是 (1, 1, 1)
// console.log('包围盒底部 Y 值:', finalBox.min.y) // 应该是 0
return geometry
}
/**
* 线 ID, 线, ID ID
*/
export function parseLineId(lineId): [LinkType, string, string] {
@ -296,7 +344,7 @@ export function deletePointByKeyboard() {
system.msg('删除了 ' + deleteCount + ' 个实体')
}
viewport.selectInspect.cancelMultiSelect()
viewport.selectManager.cancelMultiSelect()
return
}
@ -304,7 +352,7 @@ export function deletePointByKeyboard() {
// 删除实体
if (deleteEntity(entityId)) {
system.msg('删除实体 [' + entityId + '] 成功')
viewport.selectInspect.cancelSelect()
viewport.selectManager.cancelSelect()
}
})
}
@ -322,19 +370,19 @@ export function escByKeyboard(e: Event) {
viewport.interactionManager.exitInteraction()
system.msg('退出新建模式')
} else if (viewport.dragControl.isDragging) {
} else if (viewport.dragManager.isDragging) {
// 2.取消拖拽
viewport.dragControl.cancelDrag()
viewport.dragManager.cancelDrag()
system.msg('取消拖拽')
} else if (viewport.state.multiSelectedEntityIds?.length > 0) {
// 3.取消多选
viewport.selectInspect.cancelMultiSelect()
viewport.selectManager.cancelMultiSelect()
system.msg('取消多选(红选)')
} else if (viewport.state.selectedEntityId) {
// 4.取消单选
viewport.selectInspect.cancelSelect()
viewport.selectManager.cancelSelect()
system.msg('取消单选(黄选)')
}
}
@ -581,6 +629,9 @@ export function load3DModule(arrayBuffer: ArrayBuffer | string, ext: string) {
}
}
/**
* ItemJson , THREE.js
*/
export function getMatrixFromTf(tf: number[][]): THREE.Matrix4 {
const [pos, rot, scale] = tf
const matrix = new THREE.Matrix4()

47
src/core/base/BaseRenderer.ts

@ -1,6 +1,6 @@
import type Viewport from '@/core/engine/Viewport'
import * as THREE from 'three'
import { getLineId, setUserDataForItem, setUserDataForLine } from '@/core/ModelUtils.ts'
import { getLineId, getMatrixFromTf, setUserDataForItem, setUserDataForLine } from '@/core/ModelUtils.ts'
import { Line2 } from 'three/examples/jsm/lines/Line2'
import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import Constract from '@/core/Constract.ts'
@ -129,16 +129,18 @@ export default abstract class BaseRenderer {
createPoint(item: ItemJson, option?: RendererCudOption): Object3DLike {
// 由基础类创造一个属于自己的点演示
const point = this.createPointBasic(item, option)
point.setMatrix4(getMatrixFromTf(item.tf))
// point.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
//
// point.rotation.set(
// THREE.MathUtils.degToRad(item.tf[1][0]),
// THREE.MathUtils.degToRad(item.tf[1][1]),
// THREE.MathUtils.degToRad(item.tf[1][2])
// )
//
// point.scale.set(item.tf[2][0], item.tf[2][1], item.tf[2][2])
point.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
point.rotation.set(
THREE.MathUtils.degToRad(item.tf[1][0]),
THREE.MathUtils.degToRad(item.tf[1][1]),
THREE.MathUtils.degToRad(item.tf[1][2])
)
point.scale.set(item.tf[2][0], item.tf[2][1], item.tf[2][2])
point.visible = ((typeof item.v !== 'undefined') ? item.v : true)
return point
}
@ -198,18 +200,19 @@ export default abstract class BaseRenderer {
const point = object
point.name = item.name || point.name
point.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
point.rotation.set(
THREE.MathUtils.degToRad(item.tf[1][0]),
THREE.MathUtils.degToRad(item.tf[1][1]),
THREE.MathUtils.degToRad(item.tf[1][2])
)
point.scale.set(item.tf[2][0], item.tf[2][1], item.tf[2][2])
if (point instanceof PointManageWrap) {
point.manager.syncMeshObject3D(point)
}
// point.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
//
// point.rotation.set(
// THREE.MathUtils.degToRad(item.tf[1][0]),
// THREE.MathUtils.degToRad(item.tf[1][1]),
// THREE.MathUtils.degToRad(item.tf[1][2])
// )
//
// point.scale.set(item.tf[2][0], item.tf[2][1], item.tf[2][2])
// if (point instanceof PointManageWrap) {
// point.manager.syncMeshObject3D(point)
// }
point.matrix = getMatrixFromTf(item.tf)
return point
}

319
src/core/controls/DragControl.ts

@ -1,319 +0,0 @@
import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport.ts'
import { getClosestObject } from '@/core/ModelUtils.ts'
import EventBus from '@/runtime/EventBus.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import { LineManageWrap } from '@/core/manager/LineSegmentManager.ts'
/**
* ThreeJS X/Z
*/
export default class DragControl {
private viewport: Viewport
private _is_enabled: boolean = true
private domElement: HTMLElement
private isPointerDown: boolean = false
private dragStartMouse: THREE.Vector2 = new THREE.Vector2()
private checkStateInterval: number | null = null
private dragShadowsGroup: THREE.Group | null = null
private dragDelayTimeout: number | null = null
private static readonly SHADOW_MATERIAL = new THREE.MeshBasicMaterial({
color: 0x222222,
transparent: true,
opacity: 0.5,
depthWrite: false,
side: THREE.DoubleSide
})
public isDragging: boolean = false
init(viewport: Viewport): void {
this.viewport = viewport
const domElement = this.viewport.renderer.domElement
this.domElement = domElement
domElement.addEventListener('pointerdown', this.onPointerDown)
domElement.addEventListener('pointermove', this.onPointerMove)
domElement.addEventListener('pointerup', this.onPointerUp)
domElement.addEventListener('pointerleave', this.onPointerLeave)
domElement.style.cursor = 'auto'
}
/**
*
*/
dispose(): void {
if (this.domElement) {
this.domElement.removeEventListener('pointermove', this.onPointerMove)
this.domElement.removeEventListener('pointerdown', this.onPointerDown)
this.domElement.removeEventListener('pointerup', this.onPointerUp)
this.domElement.removeEventListener('pointerleave', this.onPointerLeave)
}
this.cleanupDrag()
this.viewport = null
}
/**
* pointerdown
*/
private onPointerDown = (event: PointerEvent): void => {
if (!this.enabled) return
const mouse = this.getMousePosition(event.clientX, event.clientY)
const intersected = this.getIntersectedDraggableObject(mouse)
if (!intersected) return
this.viewport.controls.enabled = false
// 设置定时器:0.1秒后才抓取拖拽
this.dragDelayTimeout = window.setTimeout(() => {
this.isPointerDown = true
this.dragStartMouse.set(intersected.position.x, intersected.position.z)
let selectedObjects = [intersected]
const multiSelected = this.viewport.state.multiSelectedObjects
if (multiSelected.length > 0 && multiSelected.includes(intersected)) {
selectedObjects = multiSelected
}
this.createShadows(selectedObjects)
this.domElement.style.cursor = 'grabbing'
this.checkStateInterval = setInterval(() => {
if (isNaN(CurrentMouseInfo.x) || isNaN(CurrentMouseInfo.z) || !this.isPointerDown) {
this.cancelDrag()
}
}, 100) // 每100毫秒检查一次状态, 鼠标移出要主动清理
}, 100) // 0.1秒延迟抓取
}
/**
* pointermove
*/
private onPointerMove = (event: PointerEvent): void => {
if (!this.enabled || !this.domElement) return
if (!isNaN(this.dragStartMouse.x) && !isNaN(this.dragStartMouse.y) && this.dragShadowsGroup) {
this.isDragging = true
this.domElement.style.cursor = 'grabbing'
this.updateShadows(new THREE.Vector2(CurrentMouseInfo.x, CurrentMouseInfo.z))
} else {
// 射线方法修改 ==========================
const mouse = this.getMousePosition(event.clientX, event.clientY)
const intersected = this.getIntersectedDraggableObject(mouse)
// =====================================
// const ids = this.viewport.itemFindManager.getItemsByPosition(CurrentMouseInfo.x, CurrentMouseInfo.z)
this.domElement.style.cursor = intersected ? 'grab' : 'auto'
}
}
/**
* pointerup
*/
private onPointerUp = (event: PointerEvent): void => {
if (this.isDragging) {
const startPos = this.dragStartMouse.clone()
const targetPos = new THREE.Vector2(CurrentMouseInfo.x, CurrentMouseInfo.z)
if (startPos && targetPos && !_.isNaN(startPos.x) && !_.isNaN(startPos.y)) {
this.dragComplete(startPos, targetPos)
}
}
this.cleanupDrag()
}
/**
*
*/
private cleanupDrag(): void {
if (this.domElement) {
this.domElement.style.cursor = 'auto'
}
this.isDragging = false
this.isPointerDown = false
this.dragStartMouse.set(NaN, NaN)
this.removeShadows()
if (this.viewport) {
this.viewport.controls.enabled = true
}
if (this.dragDelayTimeout !== null) {
clearTimeout(this.dragDelayTimeout)
this.dragDelayTimeout = null
}
if (this.checkStateInterval) {
clearInterval(this.checkStateInterval)
this.checkStateInterval = null
}
}
/**
*
*/
private getMousePosition(clientX: number, clientY: number): THREE.Vector2 {
const rect = this.domElement.getBoundingClientRect()
return new THREE.Vector2(
((clientX - rect.left) / rect.width) * 2 - 1,
((clientY - rect.top) / rect.height) * -2 + 1
)
}
/**
* 线
*/
private getIntersectedDraggableObject(mouse: THREE.Vector2): Object3DLike | undefined {
const raycaster = new THREE.Raycaster()
raycaster.setFromCamera(mouse, this.viewport.camera)
const draggableObjects = this.viewport.entityManager._draggableObjects || []
const intersects = raycaster.intersectObjects(draggableObjects, true)
if (intersects.length > 0) {
return getClosestObject(this.viewport, intersects[0].object, intersects[0].instanceId)
}
}
/**
*
*/
private createShadows(objects: Object3DLike[]): void {
this.removeShadows()
this.dragShadowsGroup = new THREE.Group()
for (const obj of objects) {
if (_.isNil(_.get(obj, 'userData.entityId'))) {
console.error(`Object ${obj.name} missing entityId`)
continue
}
// 克隆对象的几何体和材质
// const shadowBox = obj.clone()
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, DragControl.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.dragShadowsGroup.add(shadowBox)
}
this.viewport.scene.add(this.dragShadowsGroup)
}
/**
*
*/
private removeShadows(): void {
if (this.dragShadowsGroup) {
console.log('removeShadows')
this.viewport.scene.remove(this.dragShadowsGroup)
this.dragShadowsGroup = null
}
}
/**
* X/Z
*/
private updateShadows(newPosition: THREE.Vector2): void {
if (!this.dragShadowsGroup) return
// 计算新位置与拖拽开始位置的偏移量
const offsetX = newPosition.x - this.dragStartMouse.x
const offsetZ = newPosition.y - this.dragStartMouse.y
for (let i = 0; i < this.dragShadowsGroup.children.length; i++) {
const shadow = this.dragShadowsGroup.children[i] as THREE.Mesh
if (!shadow.userData.originPosition) {
console.error(`Shadow ${shadow.name} does not have originPosition`)
continue
}
const newPosX = shadow.userData.originPosition.x + offsetX
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)
}
}
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 }) => {
for (const object of this.dragShadowsGroup.children) {
const entityId = object.userData.entityId
if (entityId) {
const entity = getEntity(entityId)
// 更新实体位置
entity.tf[0][0] = object.position.x
entity.tf[0][2] = object.position.z
putEntity(entity)
} else {
system.showErrorDialog('not found entity')
}
}
})
// EventBus.dispatch('multiSelectedObjectsChanged', {
// multiSelectedObjects: this.viewport.state.multiSelectedObjects
// })
// EventBus.dispatch('selectedObjectPropertyChanged', {})
this.cleanupDrag()
}
/**
* pointerleave
*/
private onPointerLeave = (_event: PointerEvent): void => {
this.cancelDrag()
}
/**
*
*/
cancelDrag(): void {
this.cleanupDrag()
}
/**
* /
*/
public set enabled(value: boolean) {
this._is_enabled = value
if (!value) {
this.cleanupDrag()
}
}
public get enabled(): boolean {
return this._is_enabled
}
}

83
src/core/controls/MouseMoveInspect.ts

@ -1,83 +0,0 @@
import type Viewport from '@/core/engine/Viewport'
import * as THREE from 'three'
let pmFn, otFn, lvFn
/**
* designer.mousePos
*/
export default class MouseMoveInspect {
viewport: Viewport
canvas: HTMLCanvasElement
constructor() {
}
init(viewport: Viewport) {
this.viewport = viewport
this.canvas = this.viewport.renderer.domElement as HTMLCanvasElement
pmFn = this.mouseMove.bind(this)
otFn = this.mouseLv.bind(this)
lvFn = this.mouseLv.bind(this)
this.canvas.addEventListener('pointermove', pmFn)
this.canvas.addEventListener('pointerout', otFn)
this.canvas.addEventListener('mouseleave', lvFn)
}
dispose() {
this.canvas.removeEventListener('pointermove', pmFn)
pmFn = undefined
this.canvas.removeEventListener('pointerout', otFn)
otFn = undefined
this.canvas.removeEventListener('mouseleave', lvFn)
lvFn = undefined
}
mouseLv(event: MouseEvent) {
this.viewport.state.mouse.x = NaN
this.viewport.state.mouse.z = NaN
window['CurrentMouseInfo'] = {
x: NaN,
z: NaN,
isShiftKey: false,
isCtrlKey: false,
isAltKey: false,
isMetaKey: false
}
}
mouseMove = _.throttle(function(this: MouseMoveInspect, event: MouseEvent) {
const pointv = new THREE.Vector2()
pointv.x = event.offsetX / this.viewport.renderer.domElement.offsetWidth
pointv.y = event.offsetY / this.viewport.renderer.domElement.offsetHeight
const mouse = new THREE.Vector2()
mouse.set((pointv.x * 2) - 1, -(pointv.y * 2) + 1)
// 当前鼠标所在的点
const point = this.viewport.getClosestIntersection(event)
if (!point) {
return
}
this.viewport.state.mouse.x = point.x
this.viewport.state.mouse.z = point.z
window['CurrentMouseInfo'] = {
viewport: this.viewport,
x: point.x,
z: point.z,
isShiftKey: event.shiftKey,
isCtrlKey: event.ctrlKey,
isAltKey: event.altKey,
isMetaKey: event.metaKey,
mouse: mouse
}
}, 1)
animate(): void {
}
}

441
src/core/controls/SelectInspect.ts

@ -1,441 +0,0 @@
import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport'
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 EventBus from '@/runtime/EventBus'
import { markRaw } from 'vue'
import { getSetter } from '@/core/manager/ModuleManager.ts'
import Constract from '@/core/Constract.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import { getAABBox, getOBBox } from '@/core/ModelUtils.ts'
/**
*
*/
export default class SelectInspect {
viewport: Viewport
/**
* 线
*/
yellowMaterial: LineMaterial = new LineMaterial({ color: 0xffff00, linewidth: 3 })
/**
* 线
*/
redMaterial: LineMaterial = new LineMaterial({ color: 0xff0000, linewidth: 3 })
/**
*
*/
rectMaterial: THREE.MeshBasicMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
opacity: 0.3,
transparent: true
})
/**
*
*/
rectangle: THREE.Mesh | null = null
/**
* 线
*/
selectionBox: Line2
/**
* , viewport.renderer.domElement
*/
canvas: HTMLCanvasElement
/**
*
*/
recStartPos: THREE.Vector3 | null
/**
* ID
*/
selectionId: string
clickTime: number | null = null
constructor() {
}
init(viewport: Viewport) {
this.viewport = viewport
this.canvas = this.viewport.renderer.domElement as HTMLCanvasElement
// 监听 shift 按住之后的矩形
this.canvas.addEventListener('pointerdown', this.onMouseDown)
this.canvas.addEventListener('pointermove', this.onMouseMove)
this.canvas.addEventListener('pointerup', this.onMouseUp)
EventBus.on('selectedObjectChanged', this.updateSelectionBox)
EventBus.on('multiSelectedObjectsChanged', this.updateMultiSelectionBoxes)
EventBus.on('selectedObjectPropertyChanged', this.updateSelectionBox)
// EventBus.on('multiselectedObjectChanged', this.updateMultiSelectionBoxes)
}
redSelectionGroup = new THREE.Group()
updateMultiSelectionBoxes = () => {
const multiSelectedObjects = this.viewport.state.multiSelectedObjects
// 为所有多选对象创建包围盒线框
this.clearRedSelectionBoxes()
if (!multiSelectedObjects || multiSelectedObjects.length === 0) {
return
}
for (const object of multiSelectedObjects) {
if (object.userData.entityId) {
this.createRedSelectionBox(object)
}
}
}
// 取消红选
cancelMultiSelect() {
this.viewport.state.multiSelectedObjects = []
this.viewport.state.multiSelectedItems = []
this.viewport.state.multiSelectedEntityIds = []
EventBus.dispatch('multiSelectedObjectsChanged', {
viewport: markRaw(this.viewport),
multiSelectedObjects: [],
multiSelectedItems: [],
multiSelectedEntityIds: []
})
}
// 取消黄选
cancelSelect() {
this.viewport.state.selectedObject = null
this.viewport.state.selectedItem = null
this.viewport.state.selectedEntityId = null
this.viewport.state.selectedObjectSetter = null
EventBus.dispatch('selectedObjectChanged', {
viewport: markRaw(this.viewport),
selectedObject: null,
selectedItem: null,
selectedEntityId: null,
selectedObjectSetter: null
})
}
// 根据 entityId 选择对象
selectById(entityId: string | null) {
if (!entityId) {
this.viewport.state.selectedObject = null
this.viewport.state.selectedItem = null
this.viewport.state.selectedEntityId = null
this.viewport.state.selectedObjectSetter = null
EventBus.dispatch('selectedObjectChanged', {
viewport: markRaw(this.viewport),
selectedObject: null,
selectedItem: null,
selectedEntityId: null,
selectedObjectSetter: null
})
return
}
const item = this.viewport.entityManager.findItemById(entityId)
const object = this.viewport.entityManager.findObjectById(entityId)
const itemTypeName = item.t
if (item.dt.protected !== true) {
this.viewport.state.selectedObject = markRaw(object)
this.viewport.state.selectedItem = markRaw(item)
this.viewport.state.selectedEntityId = entityId
this.viewport.state.selectedObjectSetter = getSetter(itemTypeName)
EventBus.dispatch('selectedObjectChanged', {
viewport: markRaw(this.viewport),
selectedObject: this.viewport.state.selectedObject,
selectedItem: this.viewport.state.selectedItem,
selectedEntityId: this.viewport.state.selectedEntityId,
selectedObjectSetter: this.viewport.state.selectedObjectSetter
})
}
}
// 多选对象
multiSelectByIds(entityIds: string[]) {
// 遍历找到的对象,添加到多选对象中
const multiSelectedObjects = []
const multiSelectedItems = []
const multiSelectedEntityIds = []
for (const entityId of entityIds) {
const object = this.viewport.entityManager.findObjectById(entityId)
if (object.userData.entityId && object.userData.t) {
const item = this.viewport.entityManager.findItemById(object.userData.entityId)
if (item && item.dt.protected !== true) {
multiSelectedObjects.push(object)
multiSelectedItems.push(item)
multiSelectedEntityIds.push(object.userData.entityId)
}
}
}
this.viewport.state.multiSelectedObjects = markRaw(multiSelectedObjects)
this.viewport.state.multiSelectedItems = markRaw(multiSelectedItems)
this.viewport.state.multiSelectedEntityIds = multiSelectedEntityIds
EventBus.dispatch('multiSelectedObjectsChanged', {
viewport: markRaw(this.viewport),
multiSelectedObjects: this.viewport.state.multiSelectedObjects,
multiSelectedItems: this.viewport.state.multiSelectedItems,
multiSelectedEntityIds: this.viewport.state.multiSelectedEntityIds
})
}
// 清除之前的红色包围盒线框
private clearRedSelectionBoxes() {
if (this.redSelectionGroup.children.length > 0) {
for (const child of this.redSelectionGroup.children) {
this.redSelectionGroup.remove(child)
}
}
this.viewport.scene.remove(this.redSelectionGroup)
this.redSelectionGroup = new THREE.Group()
this.viewport.scene.add(this.redSelectionGroup)
}
// 创建红选包围盒
private createRedSelectionBox(object: Object3DLike) {
// 如果对象没有 entityId,则不创建包围盒线框
if (!object.userData.entityId) {
return
}
let box: THREE.Box3
if (object instanceof PointManageWrap) {
box = object.createBox3()
} else if (object instanceof THREE.Object3D) {
box = new THREE.Box3().setFromObject(object)
}
const min = box.min
const max = box.max
const corners = [
new THREE.Vector3(min.x - Constract.RED_EXPAND_AMOUNT, max.y + Constract.RED_EXPAND_AMOUNT, min.z - Constract.RED_EXPAND_AMOUNT),
new THREE.Vector3(max.x + Constract.RED_EXPAND_AMOUNT, max.y + Constract.RED_EXPAND_AMOUNT, min.z - Constract.RED_EXPAND_AMOUNT),
new THREE.Vector3(max.x + Constract.RED_EXPAND_AMOUNT, max.y + Constract.RED_EXPAND_AMOUNT, max.z + Constract.RED_EXPAND_AMOUNT),
new THREE.Vector3(min.x - Constract.RED_EXPAND_AMOUNT, max.y + Constract.RED_EXPAND_AMOUNT, max.z + Constract.RED_EXPAND_AMOUNT)
]
// 构建矩形边框(4 条边)
const positions = []
for (let i = 0; i < 4; i++) {
const p1 = corners[i]
const p2 = corners[(i + 1) % 4]
positions.push(p1.x, p1.y, p1.z)
positions.push(p2.x, p2.y, p2.z)
}
// 创建几何体
const lineGeom = new LineGeometry()
const vertices = new Float32Array(positions)
lineGeom.setPositions(vertices)
const selectionBox = new Line2(lineGeom, this.redMaterial)
selectionBox.computeLineDistances()
this.redSelectionGroup.add(selectionBox)
}
// 更新选中对象的包围盒线框
private updateSelectionBox = () => {
this.clearSelectionBox()
const item = this.viewport.state.selectedItem
if (!item) {
return
}
// 构造 positions 数组
const edgePositions = getOBBox(item) // getOBBox(item) // getAABBox(item)
const positions = []
for (let i = 0; i < edgePositions.length; i += 2) {
const p1 = edgePositions[i]
const p2 = edgePositions[i + 1]
positions.push(p1.x, p1.y, p1.z)
positions.push(p2.x, p2.y, p2.z)
}
const lineGeom = new LineGeometry().setPositions(new Float32Array(positions))
const selectionBox = new Line2(lineGeom, this.yellowMaterial)
selectionBox.computeLineDistances()
selectionBox.scale.set(1, 1, 1)
this.selectionBox = selectionBox
console.log('selectedItem', this.viewport.state.selectedItem)
this.viewport.scene.add(selectionBox)
}
dispose() {
this.canvas.removeEventListener('pointerdown', this.onMouseDown)
this.canvas.removeEventListener('pointermove', this.onMouseMove)
this.canvas.removeEventListener('pointerup', this.onMouseUp)
// 销毁选择工具
this.clearSelectionBox()
this.disposeRect()
this.clearRedSelectionBoxes()
}
// 清除当前选中对象的包围盒线框
private clearSelectionBox = () => {
if (this.selectionBox) {
this.viewport.scene.remove(this.selectionBox)
this.selectionBox.geometry.dispose()
this.selectionBox = null
}
}
private createRectangle = () => {
if (this.rectangle !== null) {
this.disposeRect()
}
if (this.recStartPos) {
// 创建矩形
this.rectangle = new THREE.Mesh(
new THREE.PlaneGeometry(0.001, 0.001),
this.rectMaterial
)
this.rectangle.name = 'selectRectangle'
this.rectangle.rotation.x = -Math.PI / 2 // 关键!让平面正对相机
this.rectangle.position.set(
this.recStartPos.x,
this.recStartPos.y,
this.recStartPos.z
)
this.viewport.scene.add(this.rectangle)
}
}
private updateRectangle = (position: THREE.Vector3) => {
if (!this.rectangle || !this.recStartPos) return
// console.log('updateRectangle', this.recStartPos, position)
const width = position.x - this.recStartPos.x
const height = position.z - this.recStartPos.z
const newWidth = Math.abs(width)
const newHeight = Math.abs(height)
// 清理旧几何体
this.rectangle.geometry.dispose()
this.rectangle.geometry = new THREE.PlaneGeometry(newWidth, newHeight)
this.rectangle.position.set(
this.recStartPos.x + width / 2,
this.recStartPos.y,
this.recStartPos.z + height / 2
)
}
private onMouseDown = (event: MouseEvent) => {
if (event.shiftKey) {
// 记录鼠标按下位置
this.recStartPos = this.viewport.getClosestIntersection(event)
this.createRectangle()
this.viewport.controls.enabled = false // 禁用控制器
} else {
// 为 click 事件添加处理逻辑
this.clickTime = Date.now()
}
}
private onMouseMove = (event: MouseEvent) => {
if (!this.recStartPos) {
this.disposeRect()
}
// 更新矩形大小或重新生成矩形
const position = this.viewport.getClosestIntersection(event)
if (!position) return
this.updateRectangle(position)
}
private onMouseUp = (event: MouseEvent) => {
this.disposeRect()
const clickTime = this.clickTime
this.clickTime = null
if (Date.now() - clickTime < 200) {
// 如果是点击事件,触发选中逻辑
const objects: Object3DLike[] = this.viewport.entityManager.getObjectByCanvasMouse(event)
if (objects.length > 0 && objects[0]?.userData?.entityId && objects[0]?.userData?.createType !== 'line') {
console.log('mouseClick', objects)
const object = objects[0]
this.selectById(object.userData.entityId)
} else {
// 如果没有选中任何对象,清除选中状态
this.selectById(null)
}
}
}
private disposeRect = () => {
if (this.rectangle !== null) {
// 查找在这个矩形内的所有有效业务对象,并将他们添加进 viewport.state.multiSelectedObjects
this.calcRectangleObjectToState()
this.viewport.scene.remove(this.rectangle)
this.rectangle.geometry.dispose()
this.rectangle = null
}
this.recStartPos = null
this.viewport.controls.enabled = true // 启用控制器
}
private calcRectangleObjectToState = () => {
if (!this.rectangle || !this.recStartPos) return
// 获取矩形的包围盒
const box = new THREE.Box3().setFromObject(this.rectangle)
// 获取盒子的 startX, startZ, endX, endZ
const startX = box.min.x
const startZ = box.min.z
const endX = box.max.x
const endZ = box.max.z
// 查找所有在矩形内的对象
const ids = this.viewport.itemFindManager.getItemsByRect(startX, startZ, endX, endZ)
// 清空之前的多选对象
this.viewport.state.multiSelectedObjects = []
// 遍历找到的对象,添加到多选对象中
const multiSelectedObjects = []
const multiSelectedItems = []
const multiSelectedEntityIds = []
for (const id of ids) {
const object = this.viewport.entityManager.findObjectById(id)
if (object.userData.entityId && object.userData.t) {
const item = this.viewport.entityManager.findItemById(object.userData.entityId)
if (item && item.dt.protected !== true) {
multiSelectedObjects.push(object)
multiSelectedItems.push(item)
multiSelectedEntityIds.push(id)
}
}
}
// 触发多选对象更新事件
this.viewport.state.multiSelectedObjects = markRaw(multiSelectedObjects)
this.viewport.state.multiSelectedItems = markRaw(multiSelectedItems)
this.viewport.state.multiSelectedEntityIds = multiSelectedEntityIds
EventBus.dispatch('multiSelectedObjectsChanged', {
viewport: markRaw(this.viewport),
multiSelectedObjects: this.viewport.state.multiSelectedObjects,
multiSelectedItems: this.viewport.state.multiSelectedItems,
multiSelectedEntityIds: this.viewport.state.multiSelectedEntityIds
})
}
}

10
src/core/engine/SceneHelp.ts

@ -36,7 +36,7 @@ export default class SceneHelp {
if (gridOption.axesEnabled) {
this.axesHelper = createAxes(gridOption.axesSize, gridOption.axesColor, gridOption.axesWidth)
this.axesHelper.position.setY(0.03) // 确保网格在地面上方
this.axesHelper.position.setY(0) // 确保网格在地面上方
this.scene.add(this.axesHelper)
}
@ -44,7 +44,7 @@ export default class SceneHelp {
gridHelper.material.color.setHex(gridOption.gridColor)
gridHelper.material.opacity = gridOption.gridOpacity
gridHelper.material.transparent = true
gridHelper.position.setY(0.02) // 确保网格在地面上方
gridHelper.position.setY(0)
gridHelper.material.vertexColors = false
if (!gridOption.gridEnabled) {
gridHelper.visible = false
@ -57,7 +57,7 @@ export default class SceneHelp {
gridHelper2.material.color.setHex(gridOption.gridColor)
gridHelper2.material.transparent = false
gridHelper2.material.vertexColors = false
gridHelper2.position.setY(0.01) // 确保网格在地面上方
gridHelper2.position.setY(0)
if (!gridOption.gridEnabled) {
gridHelper2.visible = false
}
@ -117,10 +117,6 @@ export default class SceneHelp {
} else if (obj instanceof LineManageWrap) {
// 默认会合并到 LineSegmentManager 中
} else if (obj instanceof PointManageWrap) {
if (!obj.parent) {
obj.manager.syncMeshObject3D(obj)
}
}
}
}

42
src/core/engine/Viewport.ts

@ -9,15 +9,15 @@ import { CSS3DRenderer } from 'three/examples/jsm/renderers/CSS3DRenderer'
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer'
import SceneHelp from './SceneHelp'
import SelectInspect from '../controls/SelectInspect'
import MouseMoveInspect from '../controls/MouseMoveInspect'
import SelectManager from '../manager/SelectManager'
import MouseMoveManager from '../manager/MouseMoveManager'
import EntityManager from '../manager/EntityManager'
import InteractionManager from '@/core/manager/InteractionManager'
import { calcPositionUseSnap } from '@/core/ModelUtils'
import StateManager from '@/core/manager/StateManager.ts'
import EventBus from '@/runtime/EventBus.ts'
import Constract from '@/core/Constract.ts'
import DragControl from '@/core/controls/DragControl.ts'
import DragManager from '@/core/manager/DragManager.ts'
import type { PropertySetter } from '@/core/base/PropertyTypes.ts'
import LabelManager from '@/core/manager/LabelManager.ts'
import type InstancePointManager from '@/core/manager/InstancePointManager.ts'
@ -41,9 +41,9 @@ export default class Viewport {
animationFrameId: any = null
scene: SceneHelp
selectInspect = new SelectInspect()
mouseMoveInspect = new MouseMoveInspect()
dragControl = new DragControl()
selectManager = new SelectManager()
mouseMoveManager = new MouseMoveManager()
dragManager = new DragManager()
labelManager = new LabelManager()
entityManager = new EntityManager()
itemFindManager = new ItemFindManager()
@ -53,9 +53,9 @@ export default class Viewport {
stateManager: StateManager
tools: IControls[] = [
markRaw(this.selectInspect),
markRaw(this.mouseMoveInspect),
markRaw(this.dragControl),
markRaw(this.selectManager),
markRaw(this.mouseMoveManager),
markRaw(this.dragManager),
markRaw(this.labelManager),
markRaw(this.entityManager),
markRaw(this.itemFindManager),
@ -217,10 +217,6 @@ export default class Viewport {
this.renderer = renderer
// 注册拖拽组件
// this.dragControl = new EsDragControls(this)
// 性能监控
const statsControls = new Stats()
this.statsControls = statsControls
@ -589,35 +585,15 @@ export default class Viewport {
this.renderer.domElement = null
}
if (this.interactionManager) {
this.interactionManager.dispose()
this.interactionManager = null
}
if (this.stateManager) {
this.stateManager.dispose()
this.stateManager = null
}
if (this.entityManager) {
this.entityManager.dispose()
this.entityManager = null
}
if (this.controls) {
this.controls.dispose()
this.controls = null
}
if (this.dragControl) {
this.dragControl.dispose()
this.dragControl = null
}
if (this.itemFindManager) {
this.itemFindManager.dispose()
this.itemFindManager = null
}
}
getIntersects(point: THREE.Vector2) {

4
src/core/manager/EntityManager.ts

@ -449,11 +449,11 @@ export default class EntityManager {
if (this.viewport.state.selectedEntityId === id) {
// 如果当前选中的对象被替换了,更新选中状态
this.viewport.selectInspect.selectById(id)
this.viewport.selectManager.selectById(id)
}
if (_.includes(this.viewport.state.multiSelectedEntityIds, id)) {
// 如果当前多选的对象被替换了,更新多选状态
this.viewport.selectInspect.multiSelectByIds(this.viewport.state.multiSelectedEntityIds)
this.viewport.selectManager.multiSelectByIds(this.viewport.state.multiSelectedEntityIds)
}
}

18
src/core/manager/InstanceMeshManager.ts

@ -174,6 +174,24 @@ export class InstanceMeshWrap {
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): InstanceMeshWrap {
const matrix = this.matrix
const newMatrix = matrix.multiplyMatrices(targetMatrix, matrix)
this.setMatrix4(newMatrix)
return this
}
dispose() {
this.manager.delete(this)
this.parent = null

117
src/core/manager/InstancePointManager.ts

@ -2,6 +2,8 @@ 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'
import { InstanceMeshWrap } from '@/core/manager/InstanceMeshManager.ts'
/**
*
@ -92,25 +94,27 @@ export default class InstancePointManager {
wrap.userData.t = item.t
wrap.userData.entityId = item.id
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.setMatrix4(getMatrixFromTf(item.tf))
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)
// 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)
}
/**
@ -133,30 +137,46 @@ export default class InstancePointManager {
return this.__uuidMap.get(uuid)
}
syncMeshObject3D(wrap: PointManageWrap) {
if (wrap.meshIndex < 0) {
console.error('InstancePointManager: Invalid meshIndex for wrap', wrap)
setBlockMatrixAt(wrap: PointManageWrap, matrix: THREE.Matrix4) {
const block = this.blocks[wrap.blockIndex]
if (!block) {
console.warn(`InstanceMeshManager: Block ${wrap.blockIndex} not found!`)
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) {
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, this.dummy.matrix)
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
@ -262,13 +282,12 @@ export class PointManageWrap {
uuid: string
name: string
visible: boolean
readonly position = new THREE.Vector3()
readonly rotation = new THREE.Euler()
readonly scale = new THREE.Vector3(1, 1, 1)
//@ts-ignore
userData: UserData = {}
updateWorldMatrix() {
}
get type() {
@ -291,16 +310,26 @@ export class PointManageWrap {
this.parent = null
}
applyMatrix4(matrix: THREE.Matrix4): PointManageWrap {
const position = new THREE.Vector3()
const quaternion = new THREE.Quaternion()
const scale = new THREE.Vector3()
matrix.decompose(position, quaternion, scale)
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
}
this.position.copy(position)
this.rotation.setFromQuaternion(quaternion)
this.scale.copy(scale)
this.manager.syncMeshObject3D(this)
applyMatrix4(targetMatrix: THREE.Matrix4): PointManageWrap {
const matrix = this.matrix
const newMatrix = matrix.multiplyMatrices(targetMatrix, matrix)
this.setMatrix4(newMatrix)
return this
}

6
src/core/manager/StateManager.ts

@ -175,9 +175,9 @@ export default class StateManager {
// 更新选中框
if (needDeleteSelectBox) {
this.viewport.selectInspect.selectById(null)
this.viewport.selectManager.selectById(null)
} else if (needUpdateSelectBox) {
this.viewport.selectInspect.selectById(this.viewport.state.selectedEntityId)
this.viewport.selectManager.selectById(this.viewport.state.selectedEntityId)
}
// 重新计算并更新多选框
@ -188,7 +188,7 @@ export default class StateManager {
newMultiSelectedEntityIds.push(entityId)
}
}
this.viewport.selectInspect.multiSelectByIds(newMultiSelectedEntityIds)
this.viewport.selectManager.multiSelectByIds(newMultiSelectedEntityIds)
}
// 获取被改过的数据, 覆盖之前的数据

2
src/editor/widgets/modeltree/ModeltreeViewJs.js

@ -31,7 +31,7 @@ export default defineComponent({
console.log(this.$refs.grid1, evt)
const { data } = evt
if (data?.id) {
this.viewport.selectInspect.selectById(data.id)
this.viewport.selectManager.selectById(data.id)
this.viewport.cameraToEntity(data.id)
} else {

2
src/example/ExampleUtil.js

@ -106,7 +106,7 @@ export function buildPointPerformanceData(t, rows, cols) {
node.tf[0][1] = 0.01
node.tf[0][2] = col * spacingZ
node.tf[1] = [0, 0, 0]
node.tf[2] = [1, 1.5, 1]
node.tf[2] = [1, 1, 1]
data.set(node.id, node)
}
}

76
src/example/example1.js

@ -326,10 +326,81 @@ export default {
catalogCode: 'f3', t: 'floor',
items: [
{
id: 'gs1',
t: 'gstore',
v: true,
tf: [[0, 0, 0], [0, 0, 0], [1, 0.5, 1]],
dt: { in: [], out: [], center: [] }
}
]
},
{
catalogCode: 'f5', t: 'floor',
items: [
// pallet
{
id: 'pallet1',
t: 'pallet',
v: true,
tf: [[-5, 0, -5], [0, 0, 0], [1, 1, 2]],
dt: { in: [], out: [], center: [] }
},
{
id: 'pallet2',
t: 'pallet',
v: true,
tf: [[0, 0, -5], [0, 0, 0], [1, 1, 1]],
dt: { in: [], out: [], center: [] }
},
{
id: 'pallet3',
t: 'pallet',
v: true,
tf: [[5, 0, -5], [0, 0, 0], [2, 1, 1]],
dt: { in: [], out: [], center: [] }
},
// tote
{
id: 'tote1',
t: 'tote',
v: true,
tf: [[-5, 0, 0], [0, 0, 0], [1, 1, 2]],
dt: { in: [], out: [], center: [] }
},
{
id: 'tote2',
t: 'tote',
v: true,
tf: [[0, 0, 0], [0, 0, 0], [1, 1, 1]],
dt: { in: [], out: [], center: [] }
},
{
id: 'tote3',
t: 'tote',
v: true,
tf: [[5, 0, 0], [0, 0, 0], [2, 1, 1]],
dt: { in: [], out: [], center: [] }
},
// carton
{
id: 'carton1',
t: 'carton',
v: true,
tf: [[0, 0.1, 0], [0, 0, 0], [1.0, 1.0, 1.0]],
tf: [[-5, 0, 5], [0, 0, 0], [1, 1, 2]],
dt: { in: [], out: [], center: [] }
},
{
id: 'carton2',
t: 'carton',
v: true,
tf: [[0, 0, 5], [0, 0, 0], [1, 1, 1]],
dt: { in: [], out: [], center: [] }
},
{
id: 'carton3',
t: 'carton',
v: true,
tf: [[5, 0, 5], [0, 0, 0], [2, 1, 1]],
dt: { in: [], out: [], center: [] }
}
]
@ -396,7 +467,7 @@ export default {
},
{
catalogCode: '__f2', t: 'floor',
items: buildPointPerformanceData('pallet', 200, 500)
items: buildPointPerformanceData('carton', 200, 500)
},
{
catalogCode: '__f3', t: 'floor',
@ -880,6 +951,7 @@ export default {
{ catalogCode: 'f2', label: '二楼 (f2)' },
{ catalogCode: 'f3', label: '三楼 (f3)' },
{ catalogCode: 'f4', label: 'AGV测试区 (f4)' },
{ catalogCode: 'f5', label: '标准容器 (f5)' },
{ catalogCode: 'OUT', label: '外场 (OUT)' },
{ catalogCode: 'fe', label: '楼层电梯 (fe)' }
]

23
src/modules/carton/CartonEntity.ts

@ -1,5 +1,26 @@
import BaseEntity from '@/core/base/BaseItemEntity.ts'
import Constract from '@/core/Constract.ts'
import * as THREE from 'three'
export default class PalletEntity extends BaseEntity {
export default class CartonSetting extends BaseEntity {
/**
*
*/
defulePositionY: number = Constract.HEIGHT_WAY
/**
*
*/
defaultScale: THREE.Vector3 = new THREE.Vector3(1, 1, 1)
/**
*
*/
defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0)
/**
*
*/
defaultColor: THREE.Color = new THREE.Color(0xc29a70)
}

14
src/modules/carton/CartonRenderer.ts

@ -5,7 +5,7 @@ import InstancePointManager from '@/core/manager/InstancePointManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import MODULE_GLB_File from '@/assets/Models/carton.glb?url'
import MODULE_3DS_TEX from '@/assets/Models/carton.jpg?url'
import { load3DModule, loadByUrl, loadGlbModule, loadTexture } from '@/core/ModelUtils.ts'
import { loadGlbModule, loadTexture, processModel } from '@/core/ModelUtils.ts'
/**
*
@ -34,12 +34,14 @@ export default class PalletRenderer extends BaseRenderer {
]).then(([_, glbGroup, cartonTexture]) => {
const mesh = glbGroup.children[0] as THREE.Mesh
this.cartonGeometry = mesh.geometry
this.cartonMaterial = new THREE.MeshPhongMaterial({ color: 0xc29a70 }) // mesh.material as THREE.Material
this.cartonGeometry.scale(0.01, 0.01, 0.01)
// this.cartonGeometry.rotateX(-Math.PI / 2)
this.cartonGeometry.center()
this.cartonGeometry.translate(0, 0.3, 0)
// this.cartonGeometry = mesh.geometry
// this.cartonGeometry.scale(0.01, 0.01, 0.01)
// this.cartonGeometry.center()
// this.cartonGeometry.translate(0, 0.3, 0)
this.cartonGeometry = processModel(mesh)
cartonTexture.flipY = true
cartonTexture.wrapS = THREE.RepeatWrapping

29
src/modules/pallet/PalletRenderer.ts

@ -3,9 +3,9 @@ import BaseRenderer from '@/core/base/BaseRenderer.ts'
import Constract from '@/core/Constract.ts'
import InstancePointManager from '@/core/manager/InstancePointManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import MODULE_3DS_File from '@/assets/Models/Pallet.3ds?url'
import MODULE_3DS_TEX from '@/assets/Models/PallTex.png?url'
import { load3DModule, loadByUrl, loadTexture } from '@/core/ModelUtils.ts'
import MODULE_GLB_File from '@/assets/Models/Pallet.glb?url'
import MODULE_3DS_TEX from '@/assets/Models/Pallet.jpg?url'
import { load3DModule, loadByUrl, loadGlbModule, loadTexture, processModel } from '@/core/ModelUtils.ts'
/**
*
@ -20,26 +20,35 @@ export default class PalletRenderer extends BaseRenderer {
readonly defaultScale: THREE.Vector3 = new THREE.Vector3(1, 1, 1)
readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0)
readonly defaultUserData = {
color: 0xcfc195
color: 0x2b5d94
}
palletGeometry: THREE.BufferGeometry
palletMaterial: THREE.Material
init() {
return Promise.all([
super.init(),
loadByUrl(MODULE_3DS_File),
loadGlbModule(MODULE_GLB_File),
loadTexture(MODULE_3DS_TEX)
]).then(([_, { data: queue3dsFile }, queueTexture]) => {
const mesh = load3DModule(queue3dsFile, '.3ds').children[0] as THREE.Mesh
this.palletGeometry = mesh.geometry.rotateX(-Math.PI / 2)
this.palletMaterial = mesh.material as THREE.Material
]).then(([_, glbGroup, cartonTexture]) => {
const mesh = glbGroup.children[0] as THREE.Mesh
this.palletGeometry = processModel(mesh)
this.palletMaterial = new THREE.MeshPhongMaterial({ color: 0x2b5d94 })
cartonTexture.flipY = true
cartonTexture.wrapS = THREE.RepeatWrapping
cartonTexture.wrapT = THREE.RepeatWrapping
cartonTexture.repeat.set(0.5, 0.5)
//@ts-ignore
this.palletMaterial.color.set(this.defaultUserData.color)
//@ts-ignore
this.palletMaterial.map = queueTexture
this.palletMaterial.normalMap = cartonTexture
})
}

2
src/types/ModelTypes.ts

@ -67,7 +67,7 @@ export interface PointManagerReference {
id: string
}
export type Object3DLike = Object3D | LineManageWrap | PointManageWrap | InstanceMeshWrap
export type Object3DLike = Object3D | PointManageWrap | InstanceMeshWrap
/**
* , THREE.Vector3

Loading…
Cancel
Save