import * as THREE from 'three' import BaseRenderer from '@/core/base/BaseRenderer.ts' import Constract from '@/core/Constract.ts' import { type Object3DLike } from '@/types/ModelTypes.ts' import { getMatrixFromTf } from '@/core/ModelUtils.ts' import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts' /** * 地堆货位渲染器 * 没有使用 InstanceMesh 目前性能不好 */ export default class GstoreRenderer extends BaseRenderer { static POINT_NAME = 'ground_store' /** * 默认点的高度, 防止和地面重合 */ readonly defulePositionY: number = Constract.HEIGHT_GSTORE readonly defaultScale: THREE.Vector3 = new THREE.Vector3(1.5, 1.2, 0.1) readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0) readonly defaultLineWidth: number = 0.05 readonly defaultPointOption = { weight: 0.1, width: 1.5, depth: 1.3, strokeColor: 0x038217, strokeWidth: 0.08 } pointGeometry = new THREE.BoxGeometry( 1, 1, 1 ).translate(0, 0.5, 0) pointMaterial: THREE.Material = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true, opacity: 0.5 }) strokeMaterial = new THREE.MeshBasicMaterial({ color: 0x038217, // transparent: true, // opacity: 0.2, side: THREE.DoubleSide }) strokeGeometry = new THREE.BoxGeometry(1, 1, 1) createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike { return this.pointManager.createByItem(item) } 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.') } /** * 地堆位置发生变化后, 创建地堆货位标记 * @param item * @param option * @param object */ afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: Object3DLike) { super.afterCreateOrUpdatePoint(item, option, object) // 目标物体 matrix const matrix = getMatrixFromTf(item.tf) const depth = item.dt.strokeWidth || 0.2 // 从矩阵分解位置、旋转和缩放 const position = new THREE.Vector3() const rotation = new THREE.Quaternion() const scale = new THREE.Vector3() matrix.decompose(position, rotation, scale) // 计算半尺寸(考虑建筑物缩放) const halfWidth = scale.x / 2 const halfHeight = scale.y / 2 const halfLength = scale.z / 2 const halfDepth = depth / 2 position.y = position.y + halfHeight // 计算向内偏移量(确保墙完全包含在内部) const insetX = halfWidth - halfDepth const insetZ = halfLength - halfDepth // 定义四面墙的参数:位置偏移和缩放(全部向内偏移) const walls = [ // 前墙 (Z+方向) { offset: new THREE.Vector3(0, 0, insetZ), scale: new THREE.Vector3(scale.x, scale.y, depth) }, // 后墙 (Z-方向) { offset: new THREE.Vector3(0, 0, -insetZ), scale: new THREE.Vector3(scale.x, scale.y, depth) }, // 左墙 (X-方向) { offset: new THREE.Vector3(-insetX, 0, 0), scale: new THREE.Vector3(depth, scale.y, scale.z - depth * 2) }, // 右墙 (X+方向) { offset: new THREE.Vector3(insetX, 0, 0), scale: new THREE.Vector3(depth, scale.y, scale.z - depth * 2) } ] // 为每面墙创建变换矩阵 const tempMatrix = new THREE.Matrix4() const tempPosition = new THREE.Vector3() const tempScale = new THREE.Vector3() walls.forEach((wall, i) => { tempPosition.copy(wall.offset).applyQuaternion(rotation).add(position) tempScale.copy(wall.scale) tempMatrix.compose(tempPosition, rotation, tempScale) const wrap1 = this.wallManager.create(item.id + '_' + i, {}) wrap1.setMatrix4(tempMatrix) }) } dispose() { super.dispose() this.pointGeometry.dispose() this.pointMaterial.dispose() // this.strokeMaterial.dispose() } get pointManager(): InstanceMeshManager { if (!this.tempViewport) { throw new Error('tempViewport is not set.') } return this.tempViewport.getOrCreateMeshManager(this.itemTypeName, () => // 构建 InstanceMesh 代理对象 new InstanceMeshManager(this.itemTypeName, this.tempViewport, this.pointGeometry, this.pointMaterial, true, true) ) } get wallManager(): InstanceMeshManager { if (!this.tempViewport) { throw new Error('tempViewport is not set.') } const name = 'GS_WALL' return this.tempViewport.getOrCreateMeshManager(name, () => { // 构建 LineSegment.points 代理对象 return new InstanceMeshManager(name, this.tempViewport, this.strokeGeometry, this.strokeMaterial, false, false) }) } }