diff --git a/package.json b/package.json index 9b0ff09..4e2af2e 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "vue3-menus": "^1.1.2", "three-mesh-bvh": "^0.9.0", "three-dxf-viewer": "^1.0.36", - "gsap": "^3.13.0" + "gsap": "^3.13.0", + "three-csg-ts": "^3.2.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0a0963b..c83d9ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -138,6 +138,9 @@ importers: three: specifier: ^0.177.0 version: 0.177.0 + three-csg-ts: + specifier: ^3.2.0 + version: 3.2.0(@types/three@0.176.0)(three@0.177.0) three-dxf-viewer: specifier: ^1.0.36 version: 1.0.36 @@ -1702,6 +1705,12 @@ packages: resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==} engines: {node: '>=16'} + three-csg-ts@3.2.0: + resolution: {integrity: sha512-oTYg8kdal6qgHDbso/6VzA12Udf2ic2uXhf0XlJzuSP+Gs0OUR5gTHSZ7GotAE+M/QcVlw41eOwiWZVnJG5/8w==, tarball: https://registry.npmmirror.com/three-csg-ts/-/three-csg-ts-3.2.0.tgz} + peerDependencies: + '@types/three': '>= 0.154.0' + three: '>= 0.154.0' + three-dxf-viewer@1.0.36: resolution: {integrity: sha512-Tu7k+/yCyovpMJTeQ8fpGHdjtynq66vMMXYzDCwI9prJo2dRDxig4S+ixQVuMIy3I99VZa51z5KwlkeWyCnFzQ==} @@ -3456,6 +3465,11 @@ snapshots: dependencies: copy-anything: 3.0.5 + three-csg-ts@3.2.0(@types/three@0.176.0)(three@0.177.0): + dependencies: + '@types/three': 0.176.0 + three: 0.177.0 + three-dxf-viewer@1.0.36: dependencies: dxf: 5.2.0 diff --git a/src/core/manager/TaskManager.ts b/src/core/manager/TaskManager.ts index 1bb0771..b20eef8 100644 --- a/src/core/manager/TaskManager.ts +++ b/src/core/manager/TaskManager.ts @@ -66,6 +66,31 @@ export default class TaskManager implements TaskManagerIF { }) } + addCl2ShowArm(): void { + this.taskSequence.push({ + type: "TASKTYPE_CL2_SHOW_ARM" + }) + } + + addCl2UpArm(hight: number): void { + this.taskSequence.push({ + type: "TASKTYPE_CL2_UP_ARM", + hight: hight + }) + } + + addCl2HideArm(): void { + this.taskSequence.push({ + type: "TASKTYPE_CL2_HIDE_ARM" + }) + } + + addCl2DownArm(): void { + this.taskSequence.push({ + type: "TASKTYPE_CL2_DOW_ARM" + }) + } + public runTask() { if (this.isStepRunning) { return @@ -115,6 +140,65 @@ export default class TaskManager implements TaskManagerIF { case 'TASKTYPE_UNLOAD': console.error('还没做') break + case 'TASKTYPE_CL2_SHOW_ARM': { + const agv = this.obj as THREE.Group + const agvPillar = agv.children[1] as THREE.Object3D + gsap.to(agvPillar.position, { + z: -1.2, + duration: 3, + repeat: 0, + ease: 'sine.inOut' + }).eventCallback('onComplete', () => { + this.runTask() + }) + break + } + + case 'TASKTYPE_CL2_UP_ARM': { + const agv = this.obj as THREE.Group + const agvPillar = agv.children[1] as THREE.Object3D + const agvArm = agvPillar.children[1] as THREE.Mesh + const task = this.currentTask + gsap.to(agvArm.position, { + y: task.hight, + duration: 3, + repeat: 0, + ease: 'sine.inOut' + }).eventCallback('onComplete', () => { + this.runTask() + }) + + break + } + case 'TASKTYPE_CL2_HIDE_ARM': { + const agv = this.obj as THREE.Group + const agvPillar = agv.children[1] as THREE.Object3D + gsap.to(agvPillar.position, { + z: 0, + duration: 3, + repeat: 0, + ease: 'sine.inOut' + }).eventCallback('onComplete', () => { + this.runTask() + }) + break + } + case 'TASKTYPE_CL2_DOW_ARM': { + const agv = this.obj as THREE.Group + const agvPillar = agv.children[1] as THREE.Object3D + const agvArm = agvPillar.children[1] as THREE.Mesh + + gsap.to(agvArm.position, { + y: 0, + duration: 3, + repeat: 0, + ease: 'sine.inOut' + }).eventCallback('onComplete', () => { + this.runTask() + }) + break + } + default: throw new Error('Invalid task type') } diff --git a/src/example/example1.js b/src/example/example1.js index a7f7c4f..5ab2504 100644 --- a/src/example/example1.js +++ b/src/example/example1.js @@ -237,7 +237,7 @@ export default { id: '5iKoIUBhnU08EM0IsoyOSW', t: 'way', v: true, - tf: [[2.7, 0.1, 7.632], [90, 0, 0], [0.25, 0.25, 0.1]], + tf: [[2.7, 0.1, 7.75], [90, 0, 0], [0.25, 0.25, 0.1]], dt: { in: [], out: [], center: ['55g6mUWBdozg4m2ueUEUsy'] } }, { id: '3ZP01pHXJRuyeg24oCaaMq', @@ -267,7 +267,7 @@ export default { id: '2qtxSDVn30EcI2uY4W0CWf', t: 'way', v: true, - tf: [[5.65, 0.1, 7.632], [90, 0, 0], [0.25, 0.25, 0.1]], + tf: [[5.65, 0.1, 7.75], [90, 0, 0], [0.25, 0.25, 0.1]], dt: { in: [], out: [], center: ['0aJ81sOKqm9FYo60AIQmMG'] } }, { id: 'ptr1', @@ -297,50 +297,50 @@ export default { id: 'pallet1122', t: 'pallet', v: true, - tf: [[1.5, 0.1, 0.63], [0, 0, 0], [1, 0.25, 1]], - dt: { in: [], out: [], center: [] } + tf: [[1.5, 0.1, 0.63], [0, 0, 0], [1.2, 0.15, 1]], + dt: { in: [], out: [], center: [], } }, { id: 'pallet1123', t: 'pallet', v: true, - tf: [[7.100, 0.1, 4.35], [0, 90, 0], [1, 0.25, 1]], - dt: { in: [], out: [], center: [] } + tf: [[7.100, 0.1, 4.35], [0, 0, 0], [1.2, 0.15, 1]], + dt: { in: [], out: [], center: [], } }, { id: 'pallet1124', t: 'pallet', v: true, - tf: [[4.196, 1.65, 3.95], [0, 90, 0], [1, 0.25, 1]], - dt: { in: [], out: [], center: [] } + tf: [[4.196, 1.65, 3.95], [0, 0, 0], [1.2, 0.15, 1]], + dt: { in: [], out: [], center: [], } }, { id: 'pallet1125', t: 'pallet', v: true, - tf: [[4.196, 1.65, 5.225], [0, 90, 0], [1, 0.25, 1]], - dt: { in: [], out: [], center: [] } + tf: [[4.196, 1.65, 5.225], [0, 0, 0], [1.2, 0.15, 1]], + dt: { in: [], out: [], center: [], } }, { id: 'pallet1126', t: 'pallet', v: true, - tf: [[4.196, 1.65, 7.775], [0, 90, 0], [1, 0.25, 1]], - dt: { in: [], out: [], center: [] } - }, { + tf: [[4.196, 1.65, 7.775], [0, 0, 0], [1.2, 0.15, 1]], + dt: { in: [], out: [], center: [], } + },{ id: 'pallet1127', t: 'pallet', v: true, - tf: [[4.196, 3.05, 3.95], [0, 90, 0], [1, 0.25, 1]], - dt: { in: [], out: [], center: [] } + tf: [[4.196, 3.05, 3.95], [0, 0, 0], [1.2, 0.15, 1]], + dt: { in: [], out: [], center: [], } }, { id: 'pallet1128', t: 'pallet', v: true, - tf: [[4.196, 3.05, 5.225], [0, 90, 0], [1, 0.25, 1]], - dt: { in: [], out: [], center: [] } + tf: [[4.196, 3.05, 5.225], [0, 0, 0], [1.2, 0.15, 1]], + dt: { in: [], out: [], center: [], } }, { id: 'pallet1129', t: 'pallet', v: true, - tf: [[4.196, 3.05, 7.775], [0, 90, 0], [1, 0.25, 1]], - dt: { in: [], out: [], center: [] } + tf: [[4.196, 3.05, 7.775], [0, 0, 0], [1.2, 0.15, 1]], + dt: { in: [], out: [], center: [], } }] }, { diff --git a/src/modules/ptr/PtrRenderer.ts b/src/modules/ptr/PtrRenderer.ts index 816230b..25e3eb4 100644 --- a/src/modules/ptr/PtrRenderer.ts +++ b/src/modules/ptr/PtrRenderer.ts @@ -6,6 +6,8 @@ import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js' import { decimalSumBy } from '@/core/ModelUtils' import Constract from '@/core/Constract.ts' import ptrUrl from '@/assets/images/ptr/ptr.png' +import { CSG } from 'three-csg-ts'; +import {BufferGeometry} from "three"; /** * ptr侧叉渲染器 @@ -60,27 +62,34 @@ export default class PtrRenderer extends BaseRenderer { return null } - const textureLoader = new THREE.TextureLoader() - const texture = textureLoader.load(ptrUrl) - const group = new THREE.Group() group.name = PtrRenderer.POINT_NAME - // 绘制背景矩形框 - const planeGeometry = new THREE.PlaneGeometry(item.dt.ptrWidth, item.dt.ptrDepth) - planeGeometry.rotateX(-Math.PI / 2) - const planeMaterial = new THREE.MeshLambertMaterial({ - map: texture, // 颜色贴图 - transparent: true // 允许透明纹理 - }) - const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial) - group.add(planeMesh) + const ptrPedestalGeometry = this.createPtrPedestal(item, option) + const ptrPedestalMaterial = new THREE.MeshPhongMaterial({color: 0xffdddbca}); + const ptrPedestalMesh = new THREE.Mesh(ptrPedestalGeometry, ptrPedestalMaterial); + + const ptrPillarGeometry = this.createPtrPillar(item, option); + const ptrPillarMaterial = new THREE.MeshPhongMaterial({color: 0xff6c6956}); + const ptrPillarMesh = new THREE.Mesh(ptrPillarGeometry, ptrPillarMaterial); + + const ptrForkGeometry = this.createPtrFork(item, option); + const ptrForkMaterial = new THREE.MeshPhongMaterial({color: 0xff111111}); + const ptrForkMesh = new THREE.Mesh(ptrForkGeometry, ptrForkMaterial); + + group.add(ptrPedestalMesh) + const groupPillar = new THREE.Group() + groupPillar.add(ptrPillarMesh) + groupPillar.add(ptrForkMesh) + group.add(groupPillar) // 设置位置 group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2]) return group } + + dispose() { super.dispose() this.pointMaterial?.dispose() @@ -89,4 +98,218 @@ export default class PtrRenderer extends BaseRenderer { createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D { throw new Error('Ptr createPointBasic not allow!') } + + // 创建ptr的底座 + createPtrPedestal(item: ItemJson, option?: RendererCudOption): THREE.BufferGeometry { + // 参数配置 + const radius = 0.8; // 圆半径 + const lineDist = 0.75; // 切割线距离圆心距离 + const segments = 64; // 圆的分段精度 + + // 计算切割线与圆的交点 + const intersectY = Math.sqrt(radius*radius - lineDist*lineDist); + const startAngle = Math.asin(intersectY/radius); + const endAngle = Math.acos(intersectY/radius); + + + const shape = new THREE.Shape(); + shape.moveTo(0, 0); // 起点在圆心 + shape.absarc(0, 0, 0.8, startAngle, endAngle, false); // 从0到π绘制半圆 + shape.absarc(0, 0, 0.8, startAngle + Math.PI/2, endAngle + Math.PI/2, false); + shape.absarc(0, 0, 0.8, startAngle + Math.PI, endAngle + Math.PI, false); + shape.absarc(0, 0, 0.8, startAngle + Math.PI/2 * 3, endAngle + Math.PI/2 * 3, false); + + shape.lineTo(-0.5, -intersectY) + shape.lineTo(-0.5, -intersectY + 0.17) + shape.lineTo(0.75, -intersectY + 0.17) + shape.lineTo(0.75, intersectY - 0.17) + shape.lineTo(-0.5, intersectY - 0.17) + shape.lineTo(-0.5, intersectY) + shape.closePath(); // 闭合路径 + + // 拉伸轨迹线 + const curve = new THREE.CatmullRomCurve3( + [new THREE.Vector3(0, 0.02, 0), new THREE.Vector3(0, 0.22, 0)], + false, // 闭合曲线 + 'catmullrom', + 0 + ) + + // 挤出几何图形 参数 + const options = { + steps: 1, + bevelEnabled: false, + extrudePath: curve // 设置挤出轨迹 + } + // 创建挤出几何体 + const geometry = new THREE.ExtrudeGeometry(shape, options) + const material = new THREE.MeshBasicMaterial({color: 0xffdddbca}); + const mesh = new THREE.Mesh(geometry, material); + + mesh.updateMatrix() + + // 倒角 + const shapeD = new THREE.Shape(); + shapeD.moveTo(-0.02, -0.02); + shapeD.lineTo(0.02, 0.02) + shapeD.lineTo(-0.02, 0.02) + shapeD.closePath() + + const curveD = new THREE.EllipseCurve( + 0, 0, radius, radius, 0, Math.PI * 2, false, 0 + ); + // 生成拉伸路径点 + const pointsD = curveD.getPoints(segments).map(p => + new THREE.Vector3(p.x, 0.20, p.y) + ); + // 3. 挤出成型 + const optionsD = { + steps: segments, + bevelEnabled: false, + // bevelSegments: 0.01, + extrudePath: new THREE.CatmullRomCurve3(pointsD) + }; + + const geometryD = new THREE.ExtrudeGeometry(shapeD, optionsD) + const meshD = new THREE.Mesh(geometryD, material); + meshD.updateMatrix() + + // 布尔运算 + const result = CSG.subtract(mesh, meshD) + + return result.geometry + } + + // 创建ptr的立柱 + createPtrPillar(item: ItemJson, option?: RendererCudOption): THREE.BufferGeometry { + // 606.5 + const width = 0.245 + const depth = 0.716 + const dd = 0.05 + const shape = new THREE.Shape(); + shape.moveTo(-0.728, -0.358 + dd); + shape.lineTo(-0.728 + dd, -0.358); + shape.lineTo(-0.728 + width - dd, -0.358); + shape.lineTo(-0.728 + width, -0.358 + dd); + + shape.lineTo(-0.728 + width, -0.28); + shape.lineTo(-0.728 + width - 0.08, -0.28); + shape.lineTo(-0.728 + width - 0.08, 0.28); + shape.lineTo(-0.728 + width, 0.28); + + shape.lineTo(-0.728 + width, -0.358 + depth - dd); + shape.lineTo(-0.728 + width - dd, -0.358 + depth); + shape.lineTo(-0.728 + dd, -0.358 + depth); + shape.lineTo(-0.728, -0.358 + depth - dd); + // shape.lineTo(-0.728, -0.358 + dd); + // shape.closePath() + + // 拉伸轨迹线 + const curve = new THREE.CatmullRomCurve3( + [new THREE.Vector3(0, 0.22, 0), new THREE.Vector3(0, 1.872, 0)], + false, // 闭合曲线 + 'catmullrom', + 0 + ) + + // 挤出几何图形 参数 + const options = { + steps: 1, + bevelSegments: 0.05, + bevelEnabled: true, + extrudePath: curve // 设置挤出轨迹 + } + // 创建挤出几何体 + const geometry = new THREE.ExtrudeGeometry(shape, options) + // const material = new THREE.MeshBasicMaterial({color: 0xffdddbca}); + // const mesh = new THREE.Mesh(geometry, material); + return geometry + + } + + // 创建ptr的立柱 + createPtrFork(item: ItemJson, option?: RendererCudOption): THREE.BufferGeometry { + // 606.5 + const width = 0.245 + const depth = 0.716 + const dd = 0.05 + const fd = 0.03 + const shape = new THREE.Shape(); + + shape.moveTo(-0.728 + width - 0.08, -0.28); + shape.lineTo(-0.728 + width + 0.02, -0.28); + shape.lineTo(-0.728 + width + 0.02, -0.27); + shape.lineTo(-0.728 + width + 0.02 + 1.130 - fd, -0.27); + shape.lineTo(-0.728 + width + 0.02 + 1.130, -0.27 + fd); + shape.lineTo(-0.728 + width + 0.02 + 1.130, -0.12 - fd); + shape.lineTo(-0.728 + width + 0.02 + 1.130 - fd, -0.12); + shape.lineTo(-0.728 + width + 0.02, -0.12); + shape.lineTo(-0.728 + width + 0.02, 0.12); + shape.lineTo(-0.728 + width + 0.02 + 1.130 - fd, 0.12); + shape.lineTo(-0.728 + width + 0.02 + 1.130, 0.12 + fd); + shape.lineTo(-0.728 + width + 0.02 + 1.130, 0.27 - fd); + shape.lineTo(-0.728 + width + 0.02 + 1.130 - fd, 0.27); + shape.lineTo(-0.728 + width + 0.02, 0.27); + shape.lineTo(-0.728 + width + 0.02, 0.28); + shape.lineTo(-0.728 + width - 0.08, 0.28); + + shape.closePath() + + // 拉伸轨迹线 + const curve = new THREE.CatmullRomCurve3( + [new THREE.Vector3(0, 0.02, 0), new THREE.Vector3(0, 0.482, 0)], + false, // 闭合曲线 + 'catmullrom', + 0 + ) + + // 挤出几何图形 参数 + const options = { + steps: 1, + bevelSegments: 0.05, + bevelEnabled: true, + extrudePath: curve // 设置挤出轨迹 + } + // 创建挤出几何体 + const geometry = new THREE.ExtrudeGeometry(shape, options) + const material = new THREE.MeshBasicMaterial({color: 0xffdddbca}); + const mesh = new THREE.Mesh(geometry, material); + mesh.updateMatrix() + + const shapeD = new THREE.Shape(); + + + shapeD.moveTo(-0.728 + width + 0.02, -0.3); + shapeD.lineTo(-0.728 + width + 0.02 + 1.2, -0.3); + shapeD.lineTo(-0.728 + width + 0.02 + 1.2, 0.3); + shapeD.lineTo(-0.728 + width + 0.02, 0.3); + shape.closePath() + + // 拉伸轨迹线 + const curveD = new THREE.CatmullRomCurve3( + [new THREE.Vector3(0, 0.07, 0), new THREE.Vector3(0, 0.482, 0)], + false, // 闭合曲线 + 'catmullrom', + 0 + ) + + // 挤出几何图形 参数 + const optionsD = { + steps: 1, + bevelSegments: 0.05, + bevelEnabled: true, + extrudePath: curveD // 设置挤出轨迹 + } + // 创建挤出几何体 + const geometryD = new THREE.ExtrudeGeometry(shapeD, optionsD) + const meshD = new THREE.Mesh(geometryD, material); + + meshD.updateMatrix() + + // 布尔运算 + const result = CSG.subtract(mesh, meshD) + + return result.geometry + } + } diff --git a/src/types/ScriptSupport.d.ts b/src/types/ScriptSupport.d.ts index 2ef5282..a811cb5 100644 --- a/src/types/ScriptSupport.d.ts +++ b/src/types/ScriptSupport.d.ts @@ -87,6 +87,14 @@ declare interface TaskManagerIF { */ addRotationTask(angle: number): void + addCl2ShowArm(): void + + addCl2UpArm(hight: number): void + + addCl2HideArm(): void + + addCl2DownArm(): void + /** * 执行任务 */