@fmsim/machine 2.0.0-beta.52 → 2.0.0-beta.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/factories/agv-3d.js +4 -6
- package/dist/factories/agv-3d.js.map +1 -1
- package/dist/factories/conveyor-3d.js +7 -12
- package/dist/factories/conveyor-3d.js.map +1 -1
- package/dist/factories/crane-3d.js +5 -7
- package/dist/factories/crane-3d.js.map +1 -1
- package/dist/factories/crane-rail-3d.js +4 -6
- package/dist/factories/crane-rail-3d.js.map +1 -1
- package/dist/factories/machine-3d.js +22 -13
- package/dist/factories/machine-3d.js.map +1 -1
- package/dist/factories/oht-3d.js +4 -4
- package/dist/factories/oht-3d.js.map +1 -1
- package/dist/factories/shuttle-3d.js +2 -5
- package/dist/factories/shuttle-3d.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/factories/agv-3d.ts +4 -7
- package/src/factories/conveyor-3d.ts +7 -13
- package/src/factories/crane-3d.ts +6 -8
- package/src/factories/crane-rail-3d.ts +5 -7
- package/src/factories/machine-3d.ts +23 -13
- package/src/factories/oht-3d.ts +4 -4
- package/src/factories/shuttle-3d.ts +2 -6
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@fmsim/machine",
|
|
3
3
|
"description": "Layout View를 구성하는 설비(machine)들과 유닛을 구현한 모듈입니다.",
|
|
4
4
|
"author": "heartyoh",
|
|
5
|
-
"version": "2.0.0-beta.
|
|
5
|
+
"version": "2.0.0-beta.53",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
8
8
|
"things-scene": true,
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"prettier --write"
|
|
56
56
|
]
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "32f43b7ad9ab0db3e0378c29ec43cbebf22eaecc"
|
|
59
59
|
}
|
package/src/factories/agv-3d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Based on operato-scene Vehicle3D, adapted for fmsim:
|
|
11
11
|
* - extends RealObjectGroup (Conveyor3D와 동일 패턴)
|
|
12
12
|
* - statusColor from MCSStatusMixin
|
|
13
|
-
* -
|
|
13
|
+
* - 볼륨 중심 원점 (things-scene 기본 컨벤션) - mesh 로컬 [-d/2, +d/2]
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import * as THREE from 'three'
|
|
@@ -30,10 +30,6 @@ export class AGV3D extends RealObjectGroup {
|
|
|
30
30
|
return depth || TRANSPORT_SURFACE_HEIGHT
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
protected get syncZPosOffset(): number {
|
|
34
|
-
return 0
|
|
35
|
-
}
|
|
36
|
-
|
|
37
33
|
private resolveColor(): number {
|
|
38
34
|
const comp = this.component as any
|
|
39
35
|
|
|
@@ -118,7 +114,8 @@ export class AGV3D extends RealObjectGroup {
|
|
|
118
114
|
plat.receiveShadow = true
|
|
119
115
|
|
|
120
116
|
this._ownMeshes = [bumper, body, plat]
|
|
121
|
-
|
|
117
|
+
// ownGroup이 center-origin ↔ bottom-up 좌표계 변환을 자동 처리
|
|
118
|
+
for (const m of this._ownMeshes) this.components3D.add(m)
|
|
122
119
|
}
|
|
123
120
|
|
|
124
121
|
updateDimension() {}
|
|
@@ -126,7 +123,7 @@ export class AGV3D extends RealObjectGroup {
|
|
|
126
123
|
update() {
|
|
127
124
|
// 자신의 mesh만 제거 (Carrier 등 자식 컴포넌트 3D 보존)
|
|
128
125
|
for (const m of this._ownMeshes) {
|
|
129
|
-
this.
|
|
126
|
+
this.components3D.remove(m)
|
|
130
127
|
disposeObject3D(m)
|
|
131
128
|
}
|
|
132
129
|
this._ownMeshes = []
|
|
@@ -27,12 +27,6 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
27
27
|
return depth || TRANSPORT_SURFACE_HEIGHT
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
// group origin = 바닥 (y=0). MCSRealObject3D와 동일 컨벤션.
|
|
31
|
-
// 기하는 build()에서 y=0(바닥)~y=depth(상단) 범위로 배치.
|
|
32
|
-
protected get syncZPosOffset(): number {
|
|
33
|
-
return 0
|
|
34
|
-
}
|
|
35
|
-
|
|
36
30
|
private resolveColor(): number {
|
|
37
31
|
const comp = this.component as any
|
|
38
32
|
|
|
@@ -172,7 +166,7 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
172
166
|
const frameMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(frameGeometries), frameMaterial)
|
|
173
167
|
frameMesh.castShadow = true
|
|
174
168
|
frameMesh.receiveShadow = true
|
|
175
|
-
this.
|
|
169
|
+
this.components3D.add(frameMesh)
|
|
176
170
|
|
|
177
171
|
// --- Rollers, Belt, or Rails ---
|
|
178
172
|
if (conveyorType === 'rail') {
|
|
@@ -237,7 +231,7 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
237
231
|
new THREE.MeshStandardMaterial({ color, metalness: 0.9, roughness: 0.2 })
|
|
238
232
|
)
|
|
239
233
|
rollerMesh.castShadow = true
|
|
240
|
-
this.
|
|
234
|
+
this.components3D.add(rollerMesh)
|
|
241
235
|
}
|
|
242
236
|
}
|
|
243
237
|
|
|
@@ -274,7 +268,7 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
274
268
|
new THREE.MeshStandardMaterial({ color: ROLLER_COLOR, metalness: 0.9, roughness: 0.2 })
|
|
275
269
|
)
|
|
276
270
|
drumMesh.castShadow = true
|
|
277
|
-
this.
|
|
271
|
+
this.components3D.add(drumMesh)
|
|
278
272
|
|
|
279
273
|
// Belt surface
|
|
280
274
|
const beltThickness = drumRadius * 0.12
|
|
@@ -292,7 +286,7 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
292
286
|
const flatMesh = new THREE.Mesh(flatGeo, beltMaterial)
|
|
293
287
|
flatMesh.position.set(0, beltY + drumRadius, 0)
|
|
294
288
|
flatMesh.castShadow = true
|
|
295
|
-
this.
|
|
289
|
+
this.components3D.add(flatMesh)
|
|
296
290
|
|
|
297
291
|
// Belt wrap around drums (segmented half-cylinder)
|
|
298
292
|
const wrapSegments = 12
|
|
@@ -328,7 +322,7 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
328
322
|
}
|
|
329
323
|
const wrapMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(wrapGeometries), beltMaterial)
|
|
330
324
|
wrapMesh.castShadow = true
|
|
331
|
-
this.
|
|
325
|
+
this.components3D.add(wrapMesh)
|
|
332
326
|
}
|
|
333
327
|
|
|
334
328
|
// Flat belt bottom (return path)
|
|
@@ -337,7 +331,7 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
337
331
|
: new THREE.BoxGeometry(flatLen, beltThickness, drumLength * 0.85)
|
|
338
332
|
const bottomMesh = new THREE.Mesh(bottomGeo, beltMaterial)
|
|
339
333
|
bottomMesh.position.set(0, beltY - drumRadius, 0)
|
|
340
|
-
this.
|
|
334
|
+
this.components3D.add(bottomMesh)
|
|
341
335
|
}
|
|
342
336
|
|
|
343
337
|
private buildRails(width: number, height: number, depth: number, frameH: number, railW: number, isVertical: boolean = false) {
|
|
@@ -375,7 +369,7 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
375
369
|
|
|
376
370
|
const railMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(railGeometries), railMaterial)
|
|
377
371
|
railMesh.castShadow = true
|
|
378
|
-
this.
|
|
372
|
+
this.components3D.add(railMesh)
|
|
379
373
|
}
|
|
380
374
|
|
|
381
375
|
updateDimension() {}
|
|
@@ -27,10 +27,6 @@ export class Crane3D extends RealObjectGroup {
|
|
|
27
27
|
return depth || 5 * TRANSPORT_SURFACE_HEIGHT - 2
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
protected get syncZPosOffset(): number {
|
|
31
|
-
return 0
|
|
32
|
-
}
|
|
33
|
-
|
|
34
30
|
private resolveColor(): number {
|
|
35
31
|
const comp = this.component as any
|
|
36
32
|
|
|
@@ -62,6 +58,8 @@ export class Crane3D extends RealObjectGroup {
|
|
|
62
58
|
const d = this.effectiveDepth
|
|
63
59
|
if (!w || !h) return
|
|
64
60
|
|
|
61
|
+
const inner = this.components3D
|
|
62
|
+
|
|
65
63
|
// 높이 배분: 하단 클램프 4%, 마스트 92%, 상단 클램프 4%
|
|
66
64
|
const clampH = d * 0.04
|
|
67
65
|
const mastH = d * 0.92
|
|
@@ -81,7 +79,7 @@ export class Crane3D extends RealObjectGroup {
|
|
|
81
79
|
const bottomClamp = new THREE.Mesh(bottomClampGeo, clampMat)
|
|
82
80
|
bottomClamp.position.y = clampH / 2
|
|
83
81
|
bottomClamp.castShadow = true
|
|
84
|
-
|
|
82
|
+
inner.add(bottomClamp)
|
|
85
83
|
|
|
86
84
|
// ── 2. 수직 마스트 (좌우 기둥 + 상·하 가로 연결 바) ──
|
|
87
85
|
const mastBaseY = clampH
|
|
@@ -115,7 +113,7 @@ export class Crane3D extends RealObjectGroup {
|
|
|
115
113
|
|
|
116
114
|
const mastMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(mastGeometries), mastMat)
|
|
117
115
|
mastMesh.castShadow = true
|
|
118
|
-
|
|
116
|
+
inner.add(mastMesh)
|
|
119
117
|
|
|
120
118
|
// ── 3. 캐리지 포크 (마스트 40% 높이, 양쪽으로 뻗는 포크 암) ──
|
|
121
119
|
const forkY = mastBaseY + mastH * 0.4
|
|
@@ -151,14 +149,14 @@ export class Crane3D extends RealObjectGroup {
|
|
|
151
149
|
|
|
152
150
|
const forkMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(forkGeometries), forkMat)
|
|
153
151
|
forkMesh.castShadow = true
|
|
154
|
-
|
|
152
|
+
inner.add(forkMesh)
|
|
155
153
|
|
|
156
154
|
// ── 4. 상단 클램프 (천장 레일에 물리는 가이드부) ──
|
|
157
155
|
const topClampGeo = new THREE.BoxGeometry(clampW, clampH, clampD)
|
|
158
156
|
const topClamp = new THREE.Mesh(topClampGeo, clampMat)
|
|
159
157
|
topClamp.position.y = mastBaseY + mastH + clampH / 2
|
|
160
158
|
topClamp.castShadow = true
|
|
161
|
-
|
|
159
|
+
inner.add(topClamp)
|
|
162
160
|
}
|
|
163
161
|
|
|
164
162
|
updateDimension() {}
|
|
@@ -28,10 +28,6 @@ export class CraneRail3D extends RealObjectGroup {
|
|
|
28
28
|
return depth || DEFAULT_RAIL_DEPTH
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
protected get syncZPosOffset(): number {
|
|
32
|
-
return 0
|
|
33
|
-
}
|
|
34
|
-
|
|
35
31
|
build() {
|
|
36
32
|
super.build()
|
|
37
33
|
|
|
@@ -41,6 +37,8 @@ export class CraneRail3D extends RealObjectGroup {
|
|
|
41
37
|
const d = this.effectiveDepth
|
|
42
38
|
if (!w || !h) return
|
|
43
39
|
|
|
40
|
+
const inner = this.components3D
|
|
41
|
+
|
|
44
42
|
const railH = Math.max(d * 0.02, 2) // 레일 높이 (얇은 트랙)
|
|
45
43
|
const railW = Math.max(h * 0.06, 2) // 레일 폭
|
|
46
44
|
const supportThick = Math.max(Math.min(w, h) * 0.05, 2)
|
|
@@ -67,7 +65,7 @@ export class CraneRail3D extends RealObjectGroup {
|
|
|
67
65
|
const bottomMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(bottomGeometries), railMat)
|
|
68
66
|
bottomMesh.castShadow = true
|
|
69
67
|
bottomMesh.receiveShadow = true
|
|
70
|
-
|
|
68
|
+
inner.add(bottomMesh)
|
|
71
69
|
|
|
72
70
|
// ── 천장 가이드 레일 (2개 평행 트랙) ──
|
|
73
71
|
const topGeometries: THREE.BufferGeometry[] = []
|
|
@@ -78,7 +76,7 @@ export class CraneRail3D extends RealObjectGroup {
|
|
|
78
76
|
}
|
|
79
77
|
const topMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(topGeometries), railMat)
|
|
80
78
|
topMesh.castShadow = true
|
|
81
|
-
|
|
79
|
+
inner.add(topMesh)
|
|
82
80
|
|
|
83
81
|
// ── 양 끝단 수직 지지대 (바닥~천장 연결) ──
|
|
84
82
|
const supportH = d - railH * 2
|
|
@@ -96,7 +94,7 @@ export class CraneRail3D extends RealObjectGroup {
|
|
|
96
94
|
}
|
|
97
95
|
const supportMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(supportGeometries), supportMat)
|
|
98
96
|
supportMesh.castShadow = true
|
|
99
|
-
|
|
97
|
+
inner.add(supportMesh)
|
|
100
98
|
}
|
|
101
99
|
|
|
102
100
|
updateDimension() {}
|
|
@@ -91,29 +91,35 @@ class MCSRealObject3D extends RealObjectGroup {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
protected get syncZPosOffset(): number {
|
|
94
|
+
// syncZPosOffset = placement + geometric (center origin = effectiveDepth/2)
|
|
95
|
+
// 중첩 보정(parent shift 상쇄)은 base RealObject.cz가 parent.geometricOffsetY를
|
|
96
|
+
// 빼는 방식으로 처리하므로 여기선 placement + 본인 geometric만 반환
|
|
97
|
+
const halfD = this.effectiveDepth / 2
|
|
94
98
|
// zPosOverride: 고정 높이 (OHTLine 등)
|
|
95
99
|
if (this._config.zPosOverride != null) {
|
|
96
|
-
return this._config.zPosOverride
|
|
100
|
+
return this._config.zPosOverride + halfD
|
|
97
101
|
}
|
|
98
102
|
// Port: 이송 표면 높이에 배치
|
|
99
103
|
if (this._config.defaultZPosFromParent) {
|
|
100
|
-
return TRANSPORT_SURFACE_HEIGHT
|
|
104
|
+
return TRANSPORT_SURFACE_HEIGHT + halfD
|
|
101
105
|
}
|
|
102
106
|
// Carrier: 부모 유형에 따라 배치 위치 결정
|
|
103
107
|
if (this._config.sizeRatio && this._config.sizeRatio < 1) {
|
|
104
108
|
const parentType = this.component.parent?.state?.type
|
|
105
|
-
// OHT: 그리퍼 아래에 매달림 (
|
|
109
|
+
// OHT: 그리퍼 아래에 매달림 — placement = -effectiveDepth(carrier top이 OHT bottom)
|
|
106
110
|
if (parentType === 'OHT') {
|
|
107
|
-
return -this.effectiveDepth
|
|
111
|
+
return -this.effectiveDepth + halfD
|
|
108
112
|
}
|
|
109
113
|
if (parentType === 'Port' || parentType === 'Shelf' || parentType === 'Shuttle') {
|
|
110
|
-
return
|
|
114
|
+
return halfD
|
|
111
115
|
}
|
|
112
|
-
return TRANSPORT_SURFACE_HEIGHT
|
|
116
|
+
return TRANSPORT_SURFACE_HEIGHT + halfD
|
|
113
117
|
}
|
|
114
|
-
return
|
|
118
|
+
return halfD
|
|
115
119
|
}
|
|
116
120
|
|
|
121
|
+
// geometric 부분(center origin: depth/2)은 base 기본값 사용 — override 불필요
|
|
122
|
+
|
|
117
123
|
// 컴포넌트의 상태 색상(statusColor) 또는 fillStyle → Three.js 색상 변환
|
|
118
124
|
protected resolveColor(): number {
|
|
119
125
|
const comp = this.component as any
|
|
@@ -285,11 +291,14 @@ class MCSRealObject3D extends RealObjectGroup {
|
|
|
285
291
|
}
|
|
286
292
|
|
|
287
293
|
this._ownMesh = new THREE.Mesh(geometry, meshMaterial)
|
|
288
|
-
//
|
|
289
|
-
|
|
294
|
+
// ownGroup 기준(bottom-up): mesh 바닥을 y=0에 맞추고 ownGroup이 -d/2로 shift해
|
|
295
|
+
// center-origin object3d에 정렬됨.
|
|
296
|
+
// box/hexagon (center-local geometry): y=rawDepth/2 (바닥을 0에 맞춤)
|
|
297
|
+
// plane: y=1 (바닥 살짝 띄움)
|
|
298
|
+
this._ownMesh.position.y = isPlane ? 1 : rawDepth / 2
|
|
290
299
|
this._ownMesh.castShadow = !isPlane
|
|
291
300
|
this._ownMesh.receiveShadow = true
|
|
292
|
-
this.
|
|
301
|
+
this.components3D.add(this._ownMesh)
|
|
293
302
|
}
|
|
294
303
|
|
|
295
304
|
// ── Change handling ──
|
|
@@ -384,7 +393,7 @@ class MCSRealObject3D extends RealObjectGroup {
|
|
|
384
393
|
update() {
|
|
385
394
|
// 자신의 mesh만 제거 (자식 컴포넌트 3D 오브젝트 보존)
|
|
386
395
|
if (this._ownMesh) {
|
|
387
|
-
this.
|
|
396
|
+
this.components3D.remove(this._ownMesh)
|
|
388
397
|
disposeObject3D(this._ownMesh)
|
|
389
398
|
this._ownMesh = undefined
|
|
390
399
|
}
|
|
@@ -642,8 +651,9 @@ class StockerRealObject3D extends MCSRealObject3D {
|
|
|
642
651
|
mat.polygonOffsetUnit = -2
|
|
643
652
|
|
|
644
653
|
this.gaugeMesh = new THREE.Mesh(geo, mat)
|
|
654
|
+
// ownGroup 기준(bottom-up): 볼륨 상단 = +depth. 그 위로 0.5 띄움.
|
|
645
655
|
this.gaugeMesh.position.set(0, depth + 0.5, 0)
|
|
646
|
-
this.
|
|
656
|
+
this.components3D.add(this.gaugeMesh)
|
|
647
657
|
}
|
|
648
658
|
|
|
649
659
|
private resolveGauge(data: any, mode: string) {
|
|
@@ -718,7 +728,7 @@ class StockerRealObject3D extends MCSRealObject3D {
|
|
|
718
728
|
|
|
719
729
|
private clearGauge() {
|
|
720
730
|
if (this.gaugeMesh) {
|
|
721
|
-
this.
|
|
731
|
+
this.components3D.remove(this.gaugeMesh)
|
|
722
732
|
this.gaugeMesh.geometry?.dispose()
|
|
723
733
|
const mat = this.gaugeMesh.material as THREE.MeshBasicMaterial
|
|
724
734
|
mat?.map?.dispose()
|
package/src/factories/oht-3d.ts
CHANGED
|
@@ -30,9 +30,9 @@ export class OHT3D extends RealObjectGroup {
|
|
|
30
30
|
return depth || TRANSPORT_SURFACE_HEIGHT
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
/** 천장 레일 높이에 배치 */
|
|
33
|
+
/** 천장 레일 높이에 배치 (center origin 기준: 레일 높이 + 볼륨 중심 반깊이) */
|
|
34
34
|
protected get syncZPosOffset(): number {
|
|
35
|
-
return OHT_RAIL_HEIGHT
|
|
35
|
+
return OHT_RAIL_HEIGHT + this.effectiveDepth / 2
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
private resolveColor(): number {
|
|
@@ -155,14 +155,14 @@ export class OHT3D extends RealObjectGroup {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
this._ownMeshes = [gripperMesh, armMesh, bodyMesh, trolleyMesh, ...wheelMeshes]
|
|
158
|
-
for (const m of this._ownMeshes) this.
|
|
158
|
+
for (const m of this._ownMeshes) this.components3D.add(m)
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
updateDimension() {}
|
|
162
162
|
|
|
163
163
|
update() {
|
|
164
164
|
for (const m of this._ownMeshes) {
|
|
165
|
-
this.
|
|
165
|
+
this.components3D.remove(m)
|
|
166
166
|
disposeObject3D(m)
|
|
167
167
|
}
|
|
168
168
|
this._ownMeshes = []
|
|
@@ -27,10 +27,6 @@ export class Shuttle3D extends RealObjectGroup {
|
|
|
27
27
|
return depth || TRANSPORT_SURFACE_HEIGHT
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
protected get syncZPosOffset(): number {
|
|
31
|
-
return 0
|
|
32
|
-
}
|
|
33
|
-
|
|
34
30
|
private resolveColor(): number {
|
|
35
31
|
const comp = this.component as any
|
|
36
32
|
|
|
@@ -142,14 +138,14 @@ export class Shuttle3D extends RealObjectGroup {
|
|
|
142
138
|
forkMesh.castShadow = true
|
|
143
139
|
|
|
144
140
|
this._ownMeshes = [baseMesh, mastMesh, forkMesh]
|
|
145
|
-
for (const m of this._ownMeshes) this.
|
|
141
|
+
for (const m of this._ownMeshes) this.components3D.add(m)
|
|
146
142
|
}
|
|
147
143
|
|
|
148
144
|
updateDimension() {}
|
|
149
145
|
|
|
150
146
|
update() {
|
|
151
147
|
for (const m of this._ownMeshes) {
|
|
152
|
-
this.
|
|
148
|
+
this.components3D.remove(m)
|
|
153
149
|
disposeObject3D(m)
|
|
154
150
|
}
|
|
155
151
|
this._ownMeshes = []
|