From c5386dc41d707380aa169af84406043ed9519c5d Mon Sep 17 00:00:00 2001 From: luoyifan Date: Thu, 12 Jun 2025 14:24:26 +0800 Subject: [PATCH 1/2] =?UTF-8?q?InstancePointManager=20=E9=87=87=E7=94=A8?= =?UTF-8?q?=20block=20=E8=AE=A1=E7=AE=97=EF=BC=8C=E4=B8=8D=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E7=BB=99=E5=AE=9A=E6=9C=80=E5=A4=A7=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/Constract.ts | 6 -- src/core/ModelUtils.ts | 2 +- src/core/manager/InstanceMeshBlock.ts | 70 ++++++++++++++ src/core/manager/InstancePointManager.ts | 157 +++++++++++++++++++------------ src/example/ExampleUtil.js | 1 - src/example/example1.js | 2 +- src/modules/carton/CartonRenderer.ts | 2 +- src/modules/gstore/GstoreRenderer.ts | 2 +- src/modules/measure/MeasureRenderer.ts | 2 +- src/modules/pallet/PalletRenderer.ts | 2 +- src/modules/tote/ToteRenderer.ts | 2 +- src/modules/way/WayRenderer.ts | 6 +- 12 files changed, 178 insertions(+), 76 deletions(-) create mode 100644 src/core/manager/InstanceMeshBlock.ts diff --git a/src/core/Constract.ts b/src/core/Constract.ts index 800e6b0..7c499f1 100644 --- a/src/core/Constract.ts +++ b/src/core/Constract.ts @@ -32,11 +32,5 @@ const Constract = Object.freeze({ HEIGHT_WAY: 0.01, HEIGHT_WAY_LABEL: 0.03, HEIGHT_WAY_LINE: 0.02, - - MAX_WAY_INSTANCES: 10000, - MAX_WAY_LINE_INSTANCES: 40000, - MAX_MEASURE_INSTANCES: 1000, - MAX_GSTORE_INSTANCES: 10000, - MAX_PALLET_INSTANCES: 10000 }) export default Constract diff --git a/src/core/ModelUtils.ts b/src/core/ModelUtils.ts index 9d083a5..ce43604 100644 --- a/src/core/ModelUtils.ts +++ b/src/core/ModelUtils.ts @@ -147,7 +147,7 @@ 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(instanceId) + return viewport.pointManagerMap.get(object.userData.t)?.findByMeshInstanceId(object.userData.blockIndex, instanceId) } return object } diff --git a/src/core/manager/InstanceMeshBlock.ts b/src/core/manager/InstanceMeshBlock.ts new file mode 100644 index 0000000..e3e9f42 --- /dev/null +++ b/src/core/manager/InstanceMeshBlock.ts @@ -0,0 +1,70 @@ +import * as THREE from 'three' +import type Viewport from '@/core/engine/Viewport.ts' + +export default class InstanceMeshBlock { + public readonly name: string + public readonly blockIndex: number + public readonly viewport: Viewport + public readonly instancedMesh: THREE.InstancedMesh + public readonly freeIndices: number[] = [] + + // instanceId -> itemId + public readonly __indexIdMap = new Map() + + getFreeMeshIndex(): number { + if (this.freeIndices.length === 0) { + return -1 // No free index available + } + return this.freeIndices.pop() // Return the last free index + } + + constructor(name: string, allowSelect: boolean, allowDrag: boolean, viewport: Viewport, + geometry: THREE.BufferGeometry, material: THREE.Material, + blockIndex: number, capacity: number) { + this.name = name + this.blockIndex = blockIndex + this.viewport = viewport + this.instancedMesh = new THREE.InstancedMesh(geometry, material, capacity) + this.instancedMesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage) + + console.log('createBlock: [' + blockIndex + '] created with capacity:', capacity) + 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 = 'InstanceMeshBlock_' + name + '_' + blockIndex + + const dummy = new THREE.Object3D() + dummy.scale.set(0, 0, 0) + dummy.updateMatrix() + + for (let i = 0; i < capacity; i++) { + this.instancedMesh.setMatrixAt(i, dummy.matrix) + this.freeIndices.push(i) + } + + this.instancedMesh.instanceMatrix.needsUpdate = true + } + + dispose() { + this.viewport.scene.remove(this.instancedMesh) + this.instancedMesh.geometry.dispose() + + if (this.instancedMesh.material) { + if (Array.isArray(this.instancedMesh.material)) { + this.instancedMesh.material.forEach(mat => mat.dispose()) + } else { + this.instancedMesh.material.dispose() + } + } + + this.instancedMesh.dispose() + this.__indexIdMap.clear() + this.freeIndices.length = 0 + } +} diff --git a/src/core/manager/InstancePointManager.ts b/src/core/manager/InstancePointManager.ts index 720719b..52f7f9d 100644 --- a/src/core/manager/InstancePointManager.ts +++ b/src/core/manager/InstancePointManager.ts @@ -1,23 +1,25 @@ 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' /** * 点实例管理器 + * 内部使用 InstanceMesh 用于管理大量点实例 */ export default class InstancePointManager { + public readonly name: string public readonly viewport: Viewport - public readonly instancedMesh: THREE.InstancedMesh + public readonly allowSelect: boolean + public readonly allowDrag: boolean + public readonly blockCapacity: number = 1000 // 每个 block 的容量 - private readonly freeIndices: number[] = [] - private readonly maxInstanceCount: number + public readonly blocks: InstanceMeshBlock[] = [] private readonly geometry: THREE.BufferGeometry private readonly material: THREE.Material private readonly dummy: THREE.Object3D = new THREE.Object3D() - // itemId -> instanceId + // itemId -> data private __uuidMap = new Map() - // instanceId -> itemId - private __indexIdMap = new Map() createPointSimple(id: string): PointManageWrap { //@ts-ignore @@ -38,21 +40,39 @@ export default class InstancePointManager { * @returns 分配的实例ID (如果失败返回-1) */ createPoint(item: ItemJson): PointManageWrap { - if (this.freeIndices.length === 0) { - system.showErrorDialog('InstancePointManager is full') + // 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 } - const meshIndex = this.freeIndices.pop()! - return new PointManageWrap(this, { + 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 } }) @@ -103,8 +123,12 @@ export default class InstancePointManager { /** * 获取点实例数据 */ - findByMeshInstanceId(instanceId: number): PointManageWrap { - const uuid = this.__indexIdMap.get(instanceId) + 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) } @@ -123,13 +147,14 @@ export default class InstancePointManager { } this.dummy.updateMatrix() + const block = this.blocks[wrap.blockIndex] if (!wrap.parent) { - wrap.parent = this.instancedMesh + wrap.parent = block.instancedMesh this.__uuidMap.set(wrap.uuid, wrap) - this.__indexIdMap.set(wrap.meshIndex, wrap.uuid) + block.__indexIdMap.set(wrap.meshIndex, wrap.uuid) } - this.instancedMesh.setMatrixAt(wrap.meshIndex, this.dummy.matrix) - this.instancedMesh.instanceMatrix.needsUpdate = true + block.instancedMesh.setMatrixAt(wrap.meshIndex, this.dummy.matrix) + block.instancedMesh.instanceMatrix.needsUpdate = true } /** @@ -140,16 +165,18 @@ export default class InstancePointManager { const wrap = this.__uuidMap.get(id) if (wrap === undefined) return + const block = this.blocks[wrap.blockIndex] + // 隐藏实例 this.dummy.scale.set(0, 0, 0) this.dummy.updateMatrix() - this.instancedMesh.setMatrixAt(wrap.meshIndex, this.dummy.matrix) - this.instancedMesh.instanceMatrix.needsUpdate = true + block.instancedMesh.setMatrixAt(wrap.meshIndex, this.dummy.matrix) + block.instancedMesh.instanceMatrix.needsUpdate = true // 回收索引 - this.freeIndices.push(wrap.meshIndex) + block.freeIndices.push(wrap.meshIndex) this.__uuidMap.delete(id) - this.__indexIdMap.delete(wrap.meshIndex) + block.__indexIdMap.delete(wrap.meshIndex) wrap.dispose() } @@ -159,59 +186,70 @@ export default class InstancePointManager { viewport: Viewport, geometry: THREE.BufferGeometry, material: THREE.Material, - maxInstances: number = 20000 + allowSelect: boolean, allowDrag: boolean ): InstancePointManager { - return new InstancePointManager(name, viewport, geometry, material, maxInstances) + return new InstancePointManager(name, allowSelect, allowDrag, viewport, geometry, material) } - private constructor(name: string, viewport: Viewport, geometry: THREE.BufferGeometry, material: THREE.Material, maxInstances: number) { + 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 - this.maxInstanceCount = maxInstances - - 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) - this.viewport.entityManager._selectableObjects.push(this.instancedMesh) - 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 + // 创建第一个 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() { - this.viewport.scene.remove(this.instancedMesh) - this.instancedMesh.geometry.dispose() - - if (this.instancedMesh.material) { - if (Array.isArray(this.instancedMesh.material)) { - this.instancedMesh.material.forEach(mat => mat.dispose()) - } else { - this.instancedMesh.material.dispose() - } + for (const block of this.blocks) { + block.dispose() } - - this.instancedMesh.dispose() this.__uuidMap.clear() - this.__indexIdMap.clear() - this.freeIndices.length = 0 + this.blocks.length = 0 } } export class PointManageWrap { readonly manager: InstancePointManager - meshIndex: number = -1 + readonly blockIndex: number = -1 + readonly meshIndex: number = -1 parent: THREE.Object3D | null = null uuid: string @@ -234,8 +272,9 @@ export class PointManageWrap { return false } - constructor(pointManager: InstancePointManager, data: any, meshIndex: number = -1) { + constructor(pointManager: InstancePointManager, blockIndex: number, meshIndex: number, data: any) { this.manager = pointManager + this.blockIndex = blockIndex this.meshIndex = meshIndex _.extend(this, data) } @@ -243,7 +282,6 @@ export class PointManageWrap { dispose() { this.manager.deletePoint(this.uuid) this.parent = null - this.meshIndex = -1 } applyMatrix4(matrix: THREE.Matrix4): PointManageWrap { @@ -260,7 +298,8 @@ export class PointManageWrap { } createBox3(): THREE.Box3 { - const instancedMesh = this.manager.instancedMesh + const instancedMesh = this.manager.blocks[this.blockIndex]?.instancedMesh + const matrix = new THREE.Matrix4() instancedMesh.getMatrixAt(this.meshIndex, matrix) // 创建包围盒并应用矩阵 diff --git a/src/example/ExampleUtil.js b/src/example/ExampleUtil.js index 391cefa..f91f25a 100644 --- a/src/example/ExampleUtil.js +++ b/src/example/ExampleUtil.js @@ -83,7 +83,6 @@ export function buildRackPerformanceData(rows, cols) { } } - debugger return Array.from(data.values()) } diff --git a/src/example/example1.js b/src/example/example1.js index 4e777bb..53b83d5 100644 --- a/src/example/example1.js +++ b/src/example/example1.js @@ -395,7 +395,7 @@ export default { }, { catalogCode: '__f2', t: 'floor', - items: buildPointPerformanceData('carton', 100, 100) + items: buildPointPerformanceData('carton', 200, 500) }, { catalogCode: '__f3', t: 'floor', diff --git a/src/modules/carton/CartonRenderer.ts b/src/modules/carton/CartonRenderer.ts index 80c53a2..5028d53 100644 --- a/src/modules/carton/CartonRenderer.ts +++ b/src/modules/carton/CartonRenderer.ts @@ -69,7 +69,7 @@ export default class PalletRenderer extends BaseRenderer { this.tempViewport, this.cartonGeometry, this.cartonMaterial, - Constract.MAX_PALLET_INSTANCES) + true, true) ) } diff --git a/src/modules/gstore/GstoreRenderer.ts b/src/modules/gstore/GstoreRenderer.ts index 498bde3..f68e100 100644 --- a/src/modules/gstore/GstoreRenderer.ts +++ b/src/modules/gstore/GstoreRenderer.ts @@ -55,7 +55,7 @@ export default class GstoreRenderer extends BaseRenderer { this.tempViewport, this.pointGeometry, this.pointMaterial, - Constract.MAX_GSTORE_INSTANCES) + true, true) ) } diff --git a/src/modules/measure/MeasureRenderer.ts b/src/modules/measure/MeasureRenderer.ts index da57375..d8d1b5d 100644 --- a/src/modules/measure/MeasureRenderer.ts +++ b/src/modules/measure/MeasureRenderer.ts @@ -93,7 +93,7 @@ export default class MeasureRenderer extends BaseRenderer { this.tempViewport, this.pointGeometry, this.pointMaterial, - Constract.MAX_MEASURE_INSTANCES) + true, true) ) } diff --git a/src/modules/pallet/PalletRenderer.ts b/src/modules/pallet/PalletRenderer.ts index 23cfe01..88f357a 100644 --- a/src/modules/pallet/PalletRenderer.ts +++ b/src/modules/pallet/PalletRenderer.ts @@ -57,7 +57,7 @@ export default class PalletRenderer extends BaseRenderer { this.tempViewport, this.palletGeometry, this.palletMaterial, - Constract.MAX_PALLET_INSTANCES) + true, true) ) } diff --git a/src/modules/tote/ToteRenderer.ts b/src/modules/tote/ToteRenderer.ts index 5565f36..9bdd40f 100644 --- a/src/modules/tote/ToteRenderer.ts +++ b/src/modules/tote/ToteRenderer.ts @@ -59,7 +59,7 @@ export default class PalletRenderer extends BaseRenderer { this.tempViewport, this.toteGeometry, this.toteMaterial, - Constract.MAX_PALLET_INSTANCES) + true, true) ) } diff --git a/src/modules/way/WayRenderer.ts b/src/modules/way/WayRenderer.ts index 35d6ce3..58207fd 100644 --- a/src/modules/way/WayRenderer.ts +++ b/src/modules/way/WayRenderer.ts @@ -206,7 +206,7 @@ export default class WayRenderer extends BaseRenderer { this.tempViewport, this.lineGeometry, this.lineMaterial, - Constract.MAX_WAY_LINE_INSTANCES) + false, false) ) } @@ -220,7 +220,7 @@ export default class WayRenderer extends BaseRenderer { this.tempViewport, this.pointGeometry, this.pointMaterial, - Constract.MAX_WAY_INSTANCES) + true, true) ) } @@ -234,7 +234,7 @@ export default class WayRenderer extends BaseRenderer { this.tempViewport, this.dirGeometry, this.dirMaterial, - Constract.MAX_WAY_LINE_INSTANCES) + false, false) ) } } From 56fd1d7219ef80f0e2e4cf989c1aef2b8cd34a17 Mon Sep 17 00:00:00 2001 From: luoyifan Date: Thu, 12 Jun 2025 15:37:18 +0800 Subject: [PATCH 2/2] InstanceMeshManager --- src/core/manager/InstanceMeshBlock.ts | 14 +- src/core/manager/InstanceMeshManager.ts | 151 ++++++++++++++ src/core/manager/InstancePointManager.ts | 9 +- src/modules/rack/RackRenderer.ts | 332 +++++++++++++++---------------- 4 files changed, 332 insertions(+), 174 deletions(-) create mode 100644 src/core/manager/InstanceMeshManager.ts diff --git a/src/core/manager/InstanceMeshBlock.ts b/src/core/manager/InstanceMeshBlock.ts index e3e9f42..9fd81d1 100644 --- a/src/core/manager/InstanceMeshBlock.ts +++ b/src/core/manager/InstanceMeshBlock.ts @@ -18,16 +18,16 @@ export default class InstanceMeshBlock { return this.freeIndices.pop() // Return the last free index } - constructor(name: string, allowSelect: boolean, allowDrag: boolean, viewport: Viewport, + constructor(itemTypeName: string, allowSelect: boolean, allowDrag: boolean, viewport: Viewport, geometry: THREE.BufferGeometry, material: THREE.Material, blockIndex: number, capacity: number) { - this.name = name + this.name = itemTypeName this.blockIndex = blockIndex this.viewport = viewport this.instancedMesh = new THREE.InstancedMesh(geometry, material, capacity) this.instancedMesh.instanceMatrix.setUsage(THREE.DynamicDrawUsage) - console.log('createBlock: [' + blockIndex + '] created with capacity:', capacity) + console.log('createBlock: ' + itemTypeName + '[' + blockIndex + '] capacity:', capacity) viewport.scene.add(this.instancedMesh) if (allowSelect) { this.viewport.entityManager._selectableObjects.push(this.instancedMesh) @@ -36,8 +36,12 @@ export default class InstanceMeshBlock { this.viewport.entityManager._draggableObjects.push(this.instancedMesh) } - this.instancedMesh.userData.t = name - this.instancedMesh.userData.entityId = 'InstanceMeshBlock_' + name + '_' + blockIndex + this.instancedMesh.userData.t = itemTypeName + this.instancedMesh.userData.entityId = 'InstanceMeshBlock_' + itemTypeName + '_' + blockIndex + _.extend(this.instancedMesh.userData,{ + t: itemTypeName, + blockIndex: blockIndex + }) const dummy = new THREE.Object3D() dummy.scale.set(0, 0, 0) diff --git a/src/core/manager/InstanceMeshManager.ts b/src/core/manager/InstanceMeshManager.ts new file mode 100644 index 0000000..56cde0c --- /dev/null +++ b/src/core/manager/InstanceMeshManager.ts @@ -0,0 +1,151 @@ +import * as THREE from 'three' +import type Viewport from '@/core/engine/Viewport.ts' +import InstanceMeshBlock from '@/core/manager/InstanceMeshBlock.ts' +import { PointManageWrap } from '@/core/manager/InstancePointManager.ts' + +export default class InstanceMeshManager { + private __uuidMap = new Map() + + 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() + + constructor(name: string, viewport: Viewport, allowSelect: boolean, allowDrag: boolean, + geometry: THREE.BufferGeometry, material: THREE.Material) { + this.name = name + this.viewport = viewport + this.allowSelect = allowSelect + this.allowDrag = allowDrag + this.geometry = geometry + this.material = material + } + + /** + * 获取点实例数据 + */ + findByMeshInstanceId(blockIndex: number, instanceId: number): InstanceMeshWrap { + 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) + } + + create(entityId: string): InstanceMeshWrap { + 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 InstanceMeshWrap(entityId, this, blockIndex, meshIndex) + } + + delete(wrap: InstanceMeshWrap) { + const block = this.blocks[wrap.blockIndex] + if (!block) { + console.warn(`InstanceMeshManager: Block ${wrap.blockIndex} not found for wrap ${wrap.uuid}`) + 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(wrap.uuid) + block.__indexIdMap.delete(wrap.meshIndex) + + wrap.dispose() + } + + // 创建新的 InstanceMeshBlock + createBlock(): InstanceMeshBlock { + const blockIndex = this.blocks.length + const block = new InstanceMeshBlock(this.name, this.allowSelect, this.allowDrag, + this.viewport, this.geometry, this.material, + blockIndex, this.blockCapacity) + this.blocks.push(block) + return block + } + + setBlockMatrixAt(wrap: InstanceMeshWrap, matrix: THREE.Matrix4) { + const block = this.blocks[wrap.blockIndex] + if (!block) { + console.warn(`InstanceMeshManager: Block ${wrap.blockIndex} not found!`) + return + } + this.__uuidMap.set(wrap.uuid, wrap) + block.instancedMesh.setMatrixAt(wrap.meshIndex, matrix) + wrap.parent = block.instancedMesh + wrap.visible = true // 默认可见 + block.instancedMesh.instanceMatrix.needsUpdate = true + } + + dispose() { + for (const block of this.blocks) { + block.dispose() + } + this.blocks.length = 0 // 清空 blocks 数组 + this.geometry.dispose() // 释放几何体资源 + this.material.dispose() // 释放材质资源 + console.log(`InstanceMeshManager ${this.name} disposed.`) + } +} + +export class InstanceMeshWrap { + readonly entityId: string + readonly manager: InstanceMeshManager + readonly blockIndex: number + readonly meshIndex: number + + uuid: string + parent: THREE.Object3D | null = null + name: string + visible: boolean + + constructor(entityId: string, manager: InstanceMeshManager, blockIndex: number, meshIndex: number) { + this.uuid = system.createUUID() + this.entityId = entityId + this.manager = manager + this.meshIndex = meshIndex + this.blockIndex = blockIndex + } + + syncMatrix(matrix: THREE.Matrix4): InstanceMeshWrap { + this.manager.setBlockMatrixAt(this, matrix) + return this + } + + dispose() { + this.manager.delete(this) + this.parent = null + } +} diff --git a/src/core/manager/InstancePointManager.ts b/src/core/manager/InstancePointManager.ts index 52f7f9d..e24cef3 100644 --- a/src/core/manager/InstancePointManager.ts +++ b/src/core/manager/InstancePointManager.ts @@ -163,9 +163,16 @@ export default class InstancePointManager { */ deletePoint(id: string): void { const wrap = this.__uuidMap.get(id) - if (wrap === undefined) return + 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) diff --git a/src/modules/rack/RackRenderer.ts b/src/modules/rack/RackRenderer.ts index cc3e2e3..9279bb4 100644 --- a/src/modules/rack/RackRenderer.ts +++ b/src/modules/rack/RackRenderer.ts @@ -1,16 +1,14 @@ import * as THREE from 'three' +import { BufferGeometry } from 'three' import BaseRenderer from '@/core/base/BaseRenderer.ts' -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 * as BufferGeometryUtils from "three/addons/utils/BufferGeometryUtils.js"; import { decimalSumBy } from '@/core/ModelUtils' import Constract from '@/core/Constract.ts' import Plastic_Rough_JPG from '@/assets/Models/Plastic_Rough.jpg' -import {BufferGeometry} from "three"; -import storageBar_PNG from "@/assets/Models/storageBar.png"; -import {Material} from "three/src/materials/Material"; -import {InstancedMesh} from "three/src/objects/InstancedMesh"; +import storageBar_PNG from '@/assets/Models/storageBar.png' +import { Material } from 'three/src/materials/Material' +import { InstancedMesh } from 'three/src/objects/InstancedMesh' +//@ts-ignore +import { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js' /** * 货架货位渲染器 @@ -127,7 +125,7 @@ export default class RackRenderer extends BaseRenderer { // group.add(lineT as THREE.Object3D) // } - const meshes = this.createRack(item, option); + const meshes = this.createRack(item, option) meshes.forEach(mesh => { group.add(mesh) @@ -170,52 +168,52 @@ export default class RackRenderer extends BaseRenderer { bottomLinkHeight = 0.2 barSectionPoints = [ - {x: -0.05, y: -0.05}, - {x: -0.025, y: -0.05}, - {x: -0.01, y: -0.045}, - {x: 0.05, 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} + { x: -0.05, y: -0.05 }, + { x: -0.025, y: -0.05 }, + { x: -0.01, y: -0.045 }, + { x: 0.05, 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} + { 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} + { 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); + 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); + shape.lineTo(this.barSectionPoints[i].x, this.barSectionPoints[i].y) } // 拉伸轨迹线 @@ -224,18 +222,18 @@ export default class RackRenderer extends BaseRenderer { false, // 闭合曲线 'catmullrom', 0 - ); + ) // 挤出几何图形 参数 const options = { steps: 1, bevelEnabled: false, - extrudePath: curve, // 设置挤出轨迹 - }; + extrudePath: curve // 设置挤出轨迹 + } // 创建挤出几何体 - const geometry = new THREE.ExtrudeGeometry(shape, options); + const geometry = new THREE.ExtrudeGeometry(shape, options) // 调整uv方便正确贴图 - this.resetUVs(geometry); + this.resetUVs(geometry) return geometry } @@ -244,29 +242,29 @@ export default class RackRenderer extends BaseRenderer { let textureLoader = new THREE.TextureLoader() // 加载纹理 - const textureHole = textureLoader.load(storageBar_PNG); // 孔洞 - const textureMaterial = textureLoader.load(Plastic_Rough_JPG); // 表面材质 + 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.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; + 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 { @@ -274,10 +272,10 @@ export default class RackRenderer extends BaseRenderer { const bgs: BufferGeometry[] = [] const top = vBarLength - topDistance // 创建一个形状 柱子的截面形状 - const shape = new THREE.Shape(); - shape.moveTo(this.linkBarSectionPoints[0].x, this.linkBarSectionPoints[0].y); + 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); + shape.lineTo(this.linkBarSectionPoints[i].x, this.linkBarSectionPoints[i].y) } // 拉伸轨迹线 横向 底部 @@ -286,14 +284,14 @@ export default class RackRenderer extends BaseRenderer { false, // 闭合曲线 'catmullrom', 0 - ); + ) // 挤出几何图形 参数 const optionsHBottom = { steps: 1, bevelEnabled: false, - extrudePath: curveHBottom, // 设置挤出轨迹 - }; + extrudePath: curveHBottom // 设置挤出轨迹 + } // 拉伸轨迹线 横向 底部 const curveHTop = new THREE.CatmullRomCurve3( @@ -301,99 +299,98 @@ export default class RackRenderer extends BaseRenderer { false, // 闭合曲线 'catmullrom', 0 - ); + ) // 挤出几何图形 参数 const optionsHTop = { steps: 1, bevelEnabled: false, - extrudePath: curveHTop, // 设置挤出轨迹 - }; + extrudePath: curveHTop // 设置挤出轨迹 + } // 创建挤出几何体 - const geometryHBottom = new THREE.ExtrudeGeometry(shape, optionsHBottom); - const geometryHTop = new THREE.ExtrudeGeometry(shape, optionsHTop); + const geometryHBottom = new THREE.ExtrudeGeometry(shape, optionsHBottom) + const geometryHTop = new THREE.ExtrudeGeometry(shape, optionsHTop) bgs.push(geometryHBottom, geometryHTop) - let remainingHeight = vBarLength - bottomDistance - topDistance + 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)], + (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, // 设置挤出轨迹 - }; + extrudePath: curveD // 设置挤出轨迹 + } - const geometryD = new THREE.ExtrudeGeometry(shape, optionsD); + const geometryD = new THREE.ExtrudeGeometry(shape, optionsD) bgs.push(geometryD) } if (vBarLength - bottomDistance - topDistance > depth) { - } // 调整uv方便正确贴图 // this.resetUVs(geometry); - return BufferGeometryUtils.mergeGeometries(bgs) + 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; + const material = new THREE.MeshPhongMaterial() + material.color.setHex(this.rackLinkBarColor, 'srgb') + material.specular.setHex(0xff6d6d6d, 'srgb') + material.transparent = true + material.needsUpdate = true - return material; + return material } createHorizontalBar(x, y, z, length): THREE.BufferGeometry { // 创建一个形状 柱子的截面形状 - const shape = new THREE.Shape(); - shape.moveTo(this.barSectionPoints[0].x, this.barSectionPoints[0].y); + 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); + 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)], + [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, // 设置挤出轨迹 - }; + extrudePath: curve // 设置挤出轨迹 + } // 创建挤出几何体 - const geometry = new THREE.ExtrudeGeometry(shape, options); + 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); + 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); + linkShapeL.lineTo(this.linkSectionPoints[i].x, this.linkSectionPoints[i].y) + linkShapeR.lineTo(this.linkSectionPoints[i].x + (length), this.linkSectionPoints[i].y) } // 拉伸轨迹线 @@ -402,36 +399,35 @@ export default class RackRenderer extends BaseRenderer { false, // 闭合曲线 'catmullrom', 0 - ); + ) // 挤出几何图形 参数 const linkOptions = { steps: 1, bevelEnabled: false, - extrudePath: linkCurve, // 设置挤出轨迹 - }; + extrudePath: linkCurve // 设置挤出轨迹 + } // 创建挤出几何体 - const linkGeometryL = new THREE.ExtrudeGeometry(linkShapeL, linkOptions); + const linkGeometryL = new THREE.ExtrudeGeometry(linkShapeL, linkOptions) linkGeometryL.rotateZ(-Math.PI / 2) - const linkGeometryR = new THREE.ExtrudeGeometry(linkShapeR, linkOptions); + const linkGeometryR = new THREE.ExtrudeGeometry(linkShapeR, linkOptions) linkGeometryR.rotateX(-Math.PI) linkGeometryR.rotateZ(-Math.PI / 2) - // 调整uv方便正确贴图 // this.resetUVs(geometry); - return BufferGeometryUtils.mergeGeometries([geometry, linkGeometryL, linkGeometryR]) + 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; + const material = new THREE.MeshPhongMaterial() + material.color.setHex(this.rackHorizontalBarColor, 'srgb') + material.specular.setHex(0xff6d6d6d, 'srgb') + material.transparent = true + material.needsUpdate = true - return material; + return material } createRack(item: ItemJson, option?: RendererCudOption): InstancedMesh[] { @@ -455,12 +451,12 @@ export default class RackRenderer extends BaseRenderer { 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 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}[] = []; + 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; + let distanceX = 0, distanceY = 0 for (let i = -1; i < item.dt.bays.length; i++) { if (i >= 0) { @@ -475,7 +471,7 @@ export default class RackRenderer extends BaseRenderer { sy: 1, sz: 1, rx: 0, - ry: Math.PI/2, + ry: Math.PI / 2, rz: 0, l: rackHeight }) @@ -487,29 +483,29 @@ export default class RackRenderer extends BaseRenderer { sy: 1, sz: 1, rx: 0, - ry: -Math.PI/2, + ry: -Math.PI / 2, rz: 0, l: rackHeight }) linkBarMatrix.push({ x: rackPoint.x + distanceX, y: rackPoint.y, - z: i%2 == 0 ? (rackPoint.z + item.dt.rackDepth) : rackPoint.z, + z: i % 2 == 0 ? (rackPoint.z + item.dt.rackDepth) : rackPoint.z, sx: 1, sy: 1, sz: 1, rx: 0, - ry: i%2 == 0 ? Math.PI : 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; + 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; + distanceY = this.bottomBarHeight const bay = item.dt.bays[i] for (let j = 0; j < bay.levelHeight.length; j++) { const levelHeight = bay.levelHeight[j] @@ -523,7 +519,7 @@ export default class RackRenderer extends BaseRenderer { sx: 1, sy: 0.8, sz: 1, - rx: Math.PI/2, + rx: Math.PI / 2, ry: 0, rz: 0, l: bay.bayWidth @@ -535,7 +531,7 @@ export default class RackRenderer extends BaseRenderer { sx: 1, sy: 0.8, sz: 1, - rx: -Math.PI/2, + rx: -Math.PI / 2, ry: 0, rz: 0, l: bay.bayWidth @@ -545,7 +541,7 @@ export default class RackRenderer extends BaseRenderer { distanceX += bay.bayWidth } - const meshes: InstancedMesh[] = []; + const meshes: InstancedMesh[] = [] if (vBarMatrix.length > 0) { if (!this.rackVerticalBarGeometry) { @@ -554,15 +550,15 @@ export default class RackRenderer extends BaseRenderer { if (!this.rackVerticalBarMaterial) { this.rackVerticalBarMaterial = this.createVerticalBarMaterial() } - const dummy = new THREE.Object3D(); - const vBarMesh = new THREE.InstancedMesh(this.rackVerticalBarGeometry, this.rackVerticalBarMaterial, vBarMatrix.length); + 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); + 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) } @@ -574,15 +570,15 @@ export default class RackRenderer extends BaseRenderer { if (!this.rackLinkBarMaterial) { this.rackLinkBarMaterial = this.createLinkBarMaterial() } - const dummy = new THREE.Object3D(); - const linkBarMesh = new THREE.InstancedMesh(this.rackLinkBarGeometry, this.rackLinkBarMaterial, linkBarMatrix.length); + 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); + 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) } @@ -594,51 +590,51 @@ export default class RackRenderer extends BaseRenderer { if (!this.rackHorizontalBarMaterial) { this.rackHorizontalBarMaterial = this.createHorizontalBarMaterial() } - const dummy = new THREE.Object3D(); - const hBarMesh = new THREE.InstancedMesh(this.rackHorizontalBarGeometry, this.rackHorizontalBarMaterial, hBarMatrix.length); + 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); + 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; + return meshes } - resetUVs(geometry) { - if (geometry == undefined) return; - const pos = geometry.getAttribute("position"), - nor = geometry.getAttribute("normal"), - uvs = geometry.getAttribute("uv"); + 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; + let x = 0, y = 0 - const nx = Math.abs(nor.getX(i)), ny = Math.abs(nor.getY(i)), nz = Math.abs(nor.getZ(i)); + 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); + x = pos.getZ(i) + y = pos.getY(i) } // if facing Y if (ny >= nx && ny >= nz) { - x = pos.getX(i); - y = pos.getZ(i); + x = pos.getX(i) + y = pos.getZ(i) } // if facing Z if (nz >= nx && nz >= ny) { - x = pos.getX(i); - y = pos.getY(i); + x = pos.getX(i) + y = pos.getY(i) } - uvs.setXY(i, x, y); + uvs.setXY(i, x, y) } }