@operato/scene-wheel-sorter 10.0.0-beta.1 → 10.0.0-beta.13
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/conveyor-3d.js +143 -69
- package/dist/conveyor-3d.js.map +1 -1
- package/dist/conveyor-join-3d.d.ts +1 -2
- package/dist/conveyor-join-3d.js +85 -76
- package/dist/conveyor-join-3d.js.map +1 -1
- package/dist/conveyor-join-trapezoid.d.ts +1 -0
- package/dist/conveyor-join-trapezoid.js +3 -0
- package/dist/conveyor-join-trapezoid.js.map +1 -1
- package/dist/conveyor-join.d.ts +3 -0
- package/dist/conveyor-join.js +59 -8
- package/dist/conveyor-join.js.map +1 -1
- package/dist/conveyor.d.ts +2 -0
- package/dist/conveyor.js +27 -0
- package/dist/conveyor.js.map +1 -1
- package/dist/mixin-conveyor.js +80 -1
- package/dist/mixin-conveyor.js.map +1 -1
- package/dist/scanner-3d.js +24 -23
- package/dist/scanner-3d.js.map +1 -1
- package/dist/scanner.d.ts +1 -0
- package/dist/scanner.js +3 -0
- package/dist/scanner.js.map +1 -1
- package/dist/wheel-sorter-3d.d.ts +1 -1
- package/dist/wheel-sorter-3d.js +86 -83
- package/dist/wheel-sorter-3d.js.map +1 -1
- package/dist/wheel-sorter.d.ts +1 -0
- package/dist/wheel-sorter.js +3 -0
- package/dist/wheel-sorter.js.map +1 -1
- package/package.json +2 -2
- package/translations/en.json +2 -1
- package/translations/ja.json +2 -1
- package/translations/ko.json +2 -1
- package/translations/ms.json +2 -1
- package/translations/zh.json +2 -1
package/dist/conveyor-3d.js
CHANGED
|
@@ -49,13 +49,18 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
49
49
|
}
|
|
50
50
|
build() {
|
|
51
51
|
super.build();
|
|
52
|
-
const { width, height, conveyorType = 0, value = 0, rollWidth = 10 } = this.component.state;
|
|
52
|
+
const { width, height, conveyorType = 0, value = 0, rollWidth = 10, orientation } = this.component.state;
|
|
53
53
|
const depth = this.effectiveDepth;
|
|
54
|
+
// orientation: 'horizontal' = 이송 가로, 'vertical' = 이송 세로, '' = auto(긴 방향)
|
|
55
|
+
const isVertical = orientation === 'vertical' ? true
|
|
56
|
+
: orientation === 'horizontal' ? false
|
|
57
|
+
: width < height;
|
|
54
58
|
// 프레임 두께: rollWidth(롤러 직경)와 동일 단위. 롤러를 감쌀 수 있어야 한다.
|
|
55
59
|
const rollerDiameter = Math.max(rollWidth, 2);
|
|
56
60
|
const frameH = rollerDiameter;
|
|
57
61
|
const legH = Math.max(depth - frameH, 0);
|
|
58
|
-
const
|
|
62
|
+
const beltWidth = isVertical ? width : height;
|
|
63
|
+
const railW = Math.max(beltWidth * 0.06, 2);
|
|
59
64
|
const legThickness = Math.max(railW * 0.8, 2);
|
|
60
65
|
const frameMaterial = new THREE.MeshStandardMaterial({
|
|
61
66
|
color: FRAME_COLOR,
|
|
@@ -65,40 +70,66 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
65
70
|
// --- Frame: side rails + legs + cross-bracing ---
|
|
66
71
|
const frameGeometries = [];
|
|
67
72
|
const railY = depth / 2 - frameH / 2;
|
|
68
|
-
// Side rails
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
// Side rails — 이송 방향을 따라, 벨트 양측에 배치
|
|
74
|
+
if (isVertical) {
|
|
75
|
+
for (const xSign of [-1, 1]) {
|
|
76
|
+
const rail = new THREE.BoxGeometry(railW, frameH, height);
|
|
77
|
+
rail.translate(xSign * (width / 2 - railW / 2), railY, 0);
|
|
78
|
+
frameGeometries.push(rail);
|
|
79
|
+
}
|
|
73
80
|
}
|
|
74
|
-
|
|
81
|
+
else {
|
|
82
|
+
for (const zSign of [-1, 1]) {
|
|
83
|
+
const rail = new THREE.BoxGeometry(width, frameH, railW);
|
|
84
|
+
rail.translate(0, railY, zSign * (height / 2 - railW / 2));
|
|
85
|
+
frameGeometries.push(rail);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// 4 legs at corners
|
|
75
89
|
const legTopY = depth / 2 - frameH;
|
|
76
90
|
const legCenterY = legTopY - legH / 2;
|
|
91
|
+
const legXPos = isVertical ? (width / 2 - railW / 2) : (width / 2 - legThickness / 2);
|
|
92
|
+
const legZPos = isVertical ? (height / 2 - legThickness / 2) : (height / 2 - railW / 2);
|
|
77
93
|
for (const xSign of [-1, 1]) {
|
|
78
94
|
for (const zSign of [-1, 1]) {
|
|
79
|
-
const lx = xSign * (width / 2 - legThickness / 2);
|
|
80
|
-
const lz = zSign * (height / 2 - railW / 2);
|
|
81
95
|
const leg = new THREE.BoxGeometry(legThickness, legH, legThickness);
|
|
82
|
-
leg.translate(
|
|
96
|
+
leg.translate(xSign * legXPos, legCenterY, zSign * legZPos);
|
|
83
97
|
frameGeometries.push(leg);
|
|
84
98
|
}
|
|
85
99
|
}
|
|
86
|
-
// Cross-bracing
|
|
100
|
+
// Cross-bracing
|
|
87
101
|
const braceH = legThickness * 0.6;
|
|
88
102
|
const braceW = legThickness * 0.6;
|
|
89
|
-
const braceLen = height - railW;
|
|
90
103
|
const braceY = legTopY - legH * 0.35;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
104
|
+
// 이송 방향 브레이스
|
|
105
|
+
if (isVertical) {
|
|
106
|
+
for (const xSign of [-1, 1]) {
|
|
107
|
+
const brace = new THREE.BoxGeometry(braceW, braceH, height - legThickness);
|
|
108
|
+
brace.translate(xSign * legXPos, braceY, 0);
|
|
109
|
+
frameGeometries.push(brace);
|
|
110
|
+
}
|
|
95
111
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
112
|
+
else {
|
|
113
|
+
for (const zSign of [-1, 1]) {
|
|
114
|
+
const brace = new THREE.BoxGeometry(width - legThickness, braceH, braceW);
|
|
115
|
+
brace.translate(0, braceY, zSign * legZPos);
|
|
116
|
+
frameGeometries.push(brace);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// 벨트폭 방향 브레이스
|
|
120
|
+
if (isVertical) {
|
|
121
|
+
for (const zSign of [-1, 1]) {
|
|
122
|
+
const brace = new THREE.BoxGeometry(width - railW, braceH, braceW);
|
|
123
|
+
brace.translate(0, braceY, zSign * legZPos);
|
|
124
|
+
frameGeometries.push(brace);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
for (const xSign of [-1, 1]) {
|
|
129
|
+
const brace = new THREE.BoxGeometry(braceW, braceH, height - railW);
|
|
130
|
+
brace.translate(xSign * legXPos, braceY, 0);
|
|
131
|
+
frameGeometries.push(brace);
|
|
132
|
+
}
|
|
102
133
|
}
|
|
103
134
|
const frameMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(frameGeometries), frameMaterial);
|
|
104
135
|
frameMesh.castShadow = true;
|
|
@@ -106,33 +137,47 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
106
137
|
this.object3d.add(frameMesh);
|
|
107
138
|
// --- Rollers or Belt ---
|
|
108
139
|
if (conveyorType === 1) {
|
|
109
|
-
this.buildBelt(width, height, depth, frameH, railW, value);
|
|
140
|
+
this.buildBelt(width, height, depth, frameH, railW, value, isVertical);
|
|
110
141
|
}
|
|
111
142
|
else {
|
|
112
|
-
this.buildRollers(width, height, depth, frameH, railW, rollWidth);
|
|
143
|
+
this.buildRollers(width, height, depth, frameH, railW, rollWidth, isVertical);
|
|
113
144
|
}
|
|
114
145
|
// --- Control box (motor housing at one end) ---
|
|
115
|
-
this.buildControlBox(width, height, depth, frameH, railW, value);
|
|
146
|
+
this.buildControlBox(width, height, depth, frameH, railW, value, isVertical);
|
|
116
147
|
}
|
|
117
|
-
buildRollers(width, height, depth, frameH, railW, rollWidth) {
|
|
118
|
-
// 롤러 반지름: rollWidth 속성으로 결정 (기본 10 → 직경 10)
|
|
148
|
+
buildRollers(width, height, depth, frameH, railW, rollWidth, isVertical = false) {
|
|
119
149
|
const rollerRadius = Math.max(rollWidth / 2, 1);
|
|
120
|
-
const rollerLength = height - railW * 2 - 0.5;
|
|
121
150
|
const diameter = rollerRadius * 2;
|
|
122
|
-
// 롤러 간 최소 간격 (Z-fighting 방지)
|
|
123
151
|
const step = diameter + 1;
|
|
124
|
-
// 롤러 중심 = 프레임 중심 (프레임이 롤러를 감싸도록)
|
|
125
152
|
const rollerY = depth / 2 - frameH / 2;
|
|
126
153
|
const rollerGeometries = [];
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
154
|
+
if (isVertical) {
|
|
155
|
+
// 롤러 축 = X축(가로), 이송 방향 = Z축(세로)
|
|
156
|
+
const rollerLength = width - railW * 2 - 0.5;
|
|
157
|
+
const count = Math.max(1, Math.floor(height / step));
|
|
158
|
+
const totalSpan = (count - 1) * step;
|
|
159
|
+
const startZ = -totalSpan / 2;
|
|
160
|
+
for (let i = 0; i < count; i++) {
|
|
161
|
+
const z = startZ + i * step;
|
|
162
|
+
const roller = new THREE.CylinderGeometry(rollerRadius, rollerRadius, rollerLength, 16);
|
|
163
|
+
roller.rotateZ(Math.PI / 2);
|
|
164
|
+
roller.translate(0, rollerY, z);
|
|
165
|
+
rollerGeometries.push(roller);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// 롤러 축 = Z축(세로), 이송 방향 = X축(가로)
|
|
170
|
+
const rollerLength = height - railW * 2 - 0.5;
|
|
171
|
+
const count = Math.max(1, Math.floor(width / step));
|
|
172
|
+
const totalSpan = (count - 1) * step;
|
|
173
|
+
const startX = -totalSpan / 2;
|
|
174
|
+
for (let i = 0; i < count; i++) {
|
|
175
|
+
const x = startX + i * step;
|
|
176
|
+
const roller = new THREE.CylinderGeometry(rollerRadius, rollerRadius, rollerLength, 16);
|
|
177
|
+
roller.rotateX(Math.PI / 2);
|
|
178
|
+
roller.translate(x, rollerY, 0);
|
|
179
|
+
rollerGeometries.push(roller);
|
|
180
|
+
}
|
|
136
181
|
}
|
|
137
182
|
if (rollerGeometries.length > 0) {
|
|
138
183
|
const rollerMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(rollerGeometries), new THREE.MeshStandardMaterial({ color: ROLLER_COLOR, metalness: 0.9, roughness: 0.2 }));
|
|
@@ -140,11 +185,13 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
140
185
|
this.object3d.add(rollerMesh);
|
|
141
186
|
}
|
|
142
187
|
}
|
|
143
|
-
buildBelt(width, height, depth, frameH, railW, value) {
|
|
188
|
+
buildBelt(width, height, depth, frameH, railW, value, isVertical = false) {
|
|
144
189
|
const drumRadius = frameH * 0.38;
|
|
145
|
-
const drumLength = height - railW * 2;
|
|
146
190
|
const beltY = depth / 2 - frameH / 2;
|
|
147
191
|
const fillColor = FILL_COLORS[value] ?? FILL_COLORS[0];
|
|
192
|
+
const transportLen = isVertical ? height : width;
|
|
193
|
+
const bw = isVertical ? width : height;
|
|
194
|
+
const drumLength = bw - railW * 2;
|
|
148
195
|
const rollerMaterial = new THREE.MeshStandardMaterial({
|
|
149
196
|
color: ROLLER_COLOR,
|
|
150
197
|
metalness: 0.9,
|
|
@@ -153,12 +200,18 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
153
200
|
// Two end drums
|
|
154
201
|
const drumGeometries = [];
|
|
155
202
|
const drumInset = drumRadius * 1.5;
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
for (const
|
|
203
|
+
const drum1 = -transportLen / 2 + drumInset;
|
|
204
|
+
const drum2 = transportLen / 2 - drumInset;
|
|
205
|
+
for (const dp of [drum1, drum2]) {
|
|
159
206
|
const drum = new THREE.CylinderGeometry(drumRadius, drumRadius, drumLength, 16);
|
|
160
|
-
|
|
161
|
-
|
|
207
|
+
if (isVertical) {
|
|
208
|
+
drum.rotateZ(Math.PI / 2);
|
|
209
|
+
drum.translate(0, beltY, dp);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
drum.rotateX(Math.PI / 2);
|
|
213
|
+
drum.translate(dp, beltY, 0);
|
|
214
|
+
}
|
|
162
215
|
drumGeometries.push(drum);
|
|
163
216
|
}
|
|
164
217
|
const drumMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(drumGeometries), rollerMaterial);
|
|
@@ -172,49 +225,63 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
172
225
|
roughness: 0.9
|
|
173
226
|
});
|
|
174
227
|
// Flat belt top surface spanning between drums
|
|
175
|
-
const flatLen =
|
|
176
|
-
const flatGeo =
|
|
228
|
+
const flatLen = drum2 - drum1;
|
|
229
|
+
const flatGeo = isVertical
|
|
230
|
+
? new THREE.BoxGeometry(drumLength, beltThickness, flatLen)
|
|
231
|
+
: new THREE.BoxGeometry(flatLen, beltThickness, drumLength);
|
|
177
232
|
const flatMesh = new THREE.Mesh(flatGeo, beltMaterial);
|
|
178
233
|
flatMesh.position.set(0, beltY + drumRadius, 0);
|
|
179
234
|
flatMesh.castShadow = true;
|
|
180
235
|
this.object3d.add(flatMesh);
|
|
181
|
-
// Belt wrap around drums
|
|
236
|
+
// Belt wrap around drums
|
|
182
237
|
const wrapSegments = 12;
|
|
183
|
-
for (const [
|
|
184
|
-
[
|
|
185
|
-
[
|
|
238
|
+
for (const [dp, angleStart] of [
|
|
239
|
+
[drum1, Math.PI / 2],
|
|
240
|
+
[drum2, -Math.PI / 2]
|
|
186
241
|
]) {
|
|
187
242
|
const wrapGeometries = [];
|
|
188
243
|
for (let i = 0; i < wrapSegments; i++) {
|
|
189
244
|
const a0 = angleStart + (Math.PI * i) / wrapSegments;
|
|
190
245
|
const a1 = angleStart + (Math.PI * (i + 1)) / wrapSegments;
|
|
191
246
|
const r = drumRadius + beltThickness / 2;
|
|
192
|
-
const
|
|
247
|
+
const p0 = dp + Math.cos(a0) * r;
|
|
193
248
|
const y0 = beltY + Math.sin(a0) * r;
|
|
194
|
-
const
|
|
249
|
+
const p1 = dp + Math.cos(a1) * r;
|
|
195
250
|
const y1 = beltY + Math.sin(a1) * r;
|
|
196
|
-
const segLen = Math.sqrt((
|
|
197
|
-
const segAngle = Math.atan2(y1 - y0,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
251
|
+
const segLen = Math.sqrt((p1 - p0) ** 2 + (y1 - y0) ** 2) * 1.05;
|
|
252
|
+
const segAngle = Math.atan2(y1 - y0, p1 - p0);
|
|
253
|
+
if (isVertical) {
|
|
254
|
+
const seg = new THREE.BoxGeometry(drumLength, beltThickness, segLen);
|
|
255
|
+
seg.rotateX(-segAngle);
|
|
256
|
+
seg.translate(0, (y0 + y1) / 2, (p0 + p1) / 2);
|
|
257
|
+
wrapGeometries.push(seg);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
const seg = new THREE.BoxGeometry(segLen, beltThickness, drumLength);
|
|
261
|
+
seg.rotateZ(segAngle);
|
|
262
|
+
seg.translate((p0 + p1) / 2, (y0 + y1) / 2, 0);
|
|
263
|
+
wrapGeometries.push(seg);
|
|
264
|
+
}
|
|
202
265
|
}
|
|
203
266
|
const wrapMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(wrapGeometries), beltMaterial);
|
|
204
267
|
wrapMesh.castShadow = true;
|
|
205
268
|
this.object3d.add(wrapMesh);
|
|
206
269
|
}
|
|
207
|
-
// Flat belt bottom (return path
|
|
208
|
-
const bottomGeo =
|
|
270
|
+
// Flat belt bottom (return path)
|
|
271
|
+
const bottomGeo = isVertical
|
|
272
|
+
? new THREE.BoxGeometry(drumLength * 0.85, beltThickness, flatLen)
|
|
273
|
+
: new THREE.BoxGeometry(flatLen, beltThickness, drumLength * 0.85);
|
|
209
274
|
const bottomMesh = new THREE.Mesh(bottomGeo, beltMaterial);
|
|
210
275
|
bottomMesh.position.set(0, beltY - drumRadius, 0);
|
|
211
276
|
this.object3d.add(bottomMesh);
|
|
212
277
|
}
|
|
213
278
|
/** Control box (motor/controller housing) + status indicator light */
|
|
214
|
-
buildControlBox(width, height, depth, frameH, railW, value) {
|
|
215
|
-
const
|
|
279
|
+
buildControlBox(width, height, depth, frameH, railW, value, isVertical = false) {
|
|
280
|
+
const bw = isVertical ? width : height;
|
|
281
|
+
const tl = isVertical ? height : width;
|
|
282
|
+
const boxW = Math.max(tl * 0.08, 4);
|
|
216
283
|
const boxH = frameH * 0.7;
|
|
217
|
-
const boxD = Math.max(
|
|
284
|
+
const boxD = Math.max(bw * 0.2, 4);
|
|
218
285
|
const railY = depth / 2 - frameH / 2;
|
|
219
286
|
// Box positioned at one end, attached to the side rail
|
|
220
287
|
const boxMaterial = new THREE.MeshStandardMaterial({
|
|
@@ -222,9 +289,16 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
222
289
|
metalness: 0.6,
|
|
223
290
|
roughness: 0.4
|
|
224
291
|
});
|
|
225
|
-
const boxGeo =
|
|
292
|
+
const boxGeo = isVertical
|
|
293
|
+
? new THREE.BoxGeometry(boxD, boxH, boxW)
|
|
294
|
+
: new THREE.BoxGeometry(boxW, boxH, boxD);
|
|
226
295
|
const boxMesh = new THREE.Mesh(boxGeo, boxMaterial);
|
|
227
|
-
|
|
296
|
+
if (isVertical) {
|
|
297
|
+
boxMesh.position.set(-width / 2 + railW + boxD / 2, railY - frameH / 2 - boxH / 2 + boxH * 0.15, -height / 2 + boxW / 2 + railW);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
boxMesh.position.set(-width / 2 + boxW / 2 + railW, railY - frameH / 2 - boxH / 2 + boxH * 0.15, -height / 2 + railW + boxD / 2);
|
|
301
|
+
}
|
|
228
302
|
boxMesh.castShadow = true;
|
|
229
303
|
this.object3d.add(boxMesh);
|
|
230
304
|
// Status indicator light on top of control box
|
|
@@ -246,7 +320,7 @@ export class Conveyor3D extends RealObjectGroup {
|
|
|
246
320
|
}
|
|
247
321
|
updateDimension() { }
|
|
248
322
|
onchange(after, before) {
|
|
249
|
-
if ('value' in after || 'conveyorType' in after || 'rollWidth' in after || 'width' in after || 'height' in after || 'depth' in after) {
|
|
323
|
+
if ('value' in after || 'conveyorType' in after || 'rollWidth' in after || 'orientation' in after || 'width' in after || 'height' in after || 'depth' in after) {
|
|
250
324
|
this.update();
|
|
251
325
|
return;
|
|
252
326
|
}
|
package/dist/conveyor-3d.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conveyor-3d.js","sourceRoot":"","sources":["../src/conveyor-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Straight Conveyor 3D Model\n *\n * Roller type: side rails + evenly-spaced cylindrical rollers + 4 legs with cross-bracing\n * Belt type: side rails + two end drums with belt wrapping over them + 4 legs with cross-bracing\n * Both types include a control box at one end and a status indicator light.\n */\n\nimport * as THREE from 'three'\nimport * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'\nimport { RealObjectGroup } from '@hatiolab/things-scene'\n\nconst FILL_COLORS: Record<number, number> = {\n 0: 0xcccccc, // IDLE\n 1: 0xafd0f1, // RUN\n 2: 0xafd0f1, // REVERSE\n 3: 0xffba00, // WARN\n 4: 0xe9746b // ERROR\n}\n\nconst FRAME_COLOR = 0x888899\nconst ROLLER_COLOR = 0xaaaabc\nconst CONTROL_BOX_COLOR = 0x556677\nconst STATUS_EMISSIVE: Record<number, number> = {\n 0: 0x333333,\n 1: 0x44aaff,\n 2: 0x44aaff,\n 3: 0xffaa00,\n 4: 0xff3333\n}\n\nexport class Conveyor3D extends RealObjectGroup {\n get effectiveDepth(): number {\n const { width, height, depth } = this.component.state\n return depth || Math.min(width, height) * 1.5\n }\n\n get position() {\n const { zPos = 0 } = this.component.state\n return {\n x: this.cx,\n y: zPos + this.effectiveDepth / 2,\n z: this.cy\n }\n }\n\n /**\n * syncFromObject3D 역변환 시 zPos 오프셋.\n * position.y = zPos + effectiveDepth/2 이므로, 역변환도 effectiveDepth/2를 빼야 한다.\n */\n protected get syncZPosOffset(): number {\n return this.effectiveDepth / 2\n }\n\n build() {\n super.build()\n\n const { width, height, conveyorType = 0, value = 0, rollWidth = 10 } = this.component.state\n const depth = this.effectiveDepth\n\n // 프레임 두께: rollWidth(롤러 직경)와 동일 단위. 롤러를 감쌀 수 있어야 한다.\n const rollerDiameter = Math.max(rollWidth as number, 2)\n const frameH = rollerDiameter\n const legH = Math.max(depth - frameH, 0)\n const railW = Math.max(height * 0.06, 2)\n const legThickness = Math.max(railW * 0.8, 2)\n\n const frameMaterial = new THREE.MeshStandardMaterial({\n color: FRAME_COLOR,\n metalness: 0.85,\n roughness: 0.35\n })\n\n // --- Frame: side rails + legs + cross-bracing ---\n const frameGeometries: THREE.BufferGeometry[] = []\n const railY = depth / 2 - frameH / 2\n\n // Side rails (along X)\n for (const zSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(width, frameH, railW)\n rail.translate(0, railY, zSign * (height / 2 - railW / 2))\n frameGeometries.push(rail)\n }\n\n // 4 legs at corners — 레일 바로 아래에 정렬\n const legTopY = depth / 2 - frameH\n const legCenterY = legTopY - legH / 2\n\n for (const xSign of [-1, 1]) {\n for (const zSign of [-1, 1]) {\n const lx = xSign * (width / 2 - legThickness / 2)\n const lz = zSign * (height / 2 - railW / 2)\n const leg = new THREE.BoxGeometry(legThickness, legH, legThickness)\n leg.translate(lx, legCenterY, lz)\n frameGeometries.push(leg)\n }\n }\n\n // Cross-bracing: 다리 사이 연결\n const braceH = legThickness * 0.6\n const braceW = legThickness * 0.6\n const braceLen = height - railW\n const braceY = legTopY - legH * 0.35\n\n for (const xSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(braceW, braceH, braceLen)\n brace.translate(xSign * (width / 2 - legThickness / 2), braceY, 0)\n frameGeometries.push(brace)\n }\n\n // Cross-bracing: 좌우 다리 연결\n const braceLenX = width - legThickness\n for (const zSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(braceLenX, braceH, braceW)\n brace.translate(0, braceY, zSign * (height / 2 - railW / 2))\n frameGeometries.push(brace)\n }\n\n const frameMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(frameGeometries), frameMaterial)\n frameMesh.castShadow = true\n frameMesh.receiveShadow = true\n this.object3d.add(frameMesh)\n\n // --- Rollers or Belt ---\n if (conveyorType === 1) {\n this.buildBelt(width, height, depth, frameH, railW, value)\n } else {\n this.buildRollers(width, height, depth, frameH, railW, rollWidth as number)\n }\n\n // --- Control box (motor housing at one end) ---\n this.buildControlBox(width, height, depth, frameH, railW, value)\n }\n\n private buildRollers(width: number, height: number, depth: number, frameH: number, railW: number, rollWidth: number) {\n // 롤러 반지름: rollWidth 속성으로 결정 (기본 10 → 직경 10)\n const rollerRadius = Math.max(rollWidth / 2, 1)\n const rollerLength = height - railW * 2 - 0.5\n const diameter = rollerRadius * 2\n // 롤러 간 최소 간격 (Z-fighting 방지)\n const step = diameter + 1\n // 롤러 중심 = 프레임 중심 (프레임이 롤러를 감싸도록)\n const rollerY = depth / 2 - frameH / 2\n\n const rollerGeometries: THREE.BufferGeometry[] = []\n const count = Math.max(1, Math.floor(width / step))\n const totalSpan = (count - 1) * step\n const startX = -totalSpan / 2\n\n for (let i = 0; i < count; i++) {\n const x = startX + i * step\n const roller = new THREE.CylinderGeometry(rollerRadius, rollerRadius, rollerLength, 16)\n roller.rotateX(Math.PI / 2)\n roller.translate(x, rollerY, 0)\n rollerGeometries.push(roller)\n }\n\n if (rollerGeometries.length > 0) {\n const rollerMesh = new THREE.Mesh(\n BufferGeometryUtils.mergeGeometries(rollerGeometries),\n new THREE.MeshStandardMaterial({ color: ROLLER_COLOR, metalness: 0.9, roughness: 0.2 })\n )\n rollerMesh.castShadow = true\n this.object3d.add(rollerMesh)\n }\n }\n\n private buildBelt(width: number, height: number, depth: number, frameH: number, railW: number, value: number) {\n const drumRadius = frameH * 0.38\n const drumLength = height - railW * 2\n const beltY = depth / 2 - frameH / 2\n const fillColor = FILL_COLORS[value] ?? FILL_COLORS[0]\n\n const rollerMaterial = new THREE.MeshStandardMaterial({\n color: ROLLER_COLOR,\n metalness: 0.9,\n roughness: 0.2\n })\n\n // Two end drums\n const drumGeometries: THREE.BufferGeometry[] = []\n const drumInset = drumRadius * 1.5\n const leftDrumX = -width / 2 + drumInset\n const rightDrumX = width / 2 - drumInset\n\n for (const dx of [leftDrumX, rightDrumX]) {\n const drum = new THREE.CylinderGeometry(drumRadius, drumRadius, drumLength, 16)\n drum.rotateX(Math.PI / 2)\n drum.translate(dx, beltY, 0)\n drumGeometries.push(drum)\n }\n\n const drumMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(drumGeometries), rollerMaterial)\n drumMesh.castShadow = true\n this.object3d.add(drumMesh)\n\n // Belt surface: flat top + half-cylinder wraps around each drum end\n const beltThickness = drumRadius * 0.12\n const beltMaterial = new THREE.MeshStandardMaterial({\n color: fillColor,\n metalness: 0.0,\n roughness: 0.9\n })\n\n // Flat belt top surface spanning between drums\n const flatLen = rightDrumX - leftDrumX\n const flatGeo = new THREE.BoxGeometry(flatLen, beltThickness, drumLength)\n const flatMesh = new THREE.Mesh(flatGeo, beltMaterial)\n flatMesh.position.set(0, beltY + drumRadius, 0)\n flatMesh.castShadow = true\n this.object3d.add(flatMesh)\n\n // Belt wrap around drums (half-torus shape using extruded half-circle)\n const wrapSegments = 12\n for (const [dx, angleStart] of [\n [leftDrumX, Math.PI / 2],\n [rightDrumX, -Math.PI / 2]\n ] as [number, number][]) {\n const wrapGeometries: THREE.BufferGeometry[] = []\n for (let i = 0; i < wrapSegments; i++) {\n const a0 = angleStart + (Math.PI * i) / wrapSegments\n const a1 = angleStart + (Math.PI * (i + 1)) / wrapSegments\n const r = drumRadius + beltThickness / 2\n\n const x0 = dx + Math.cos(a0) * r\n const y0 = beltY + Math.sin(a0) * r\n const x1 = dx + Math.cos(a1) * r\n const y1 = beltY + Math.sin(a1) * r\n\n const segLen = Math.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2) * 1.05\n const segAngle = Math.atan2(y1 - y0, x1 - x0)\n\n const seg = new THREE.BoxGeometry(segLen, beltThickness, drumLength)\n seg.rotateZ(segAngle)\n seg.translate((x0 + x1) / 2, (y0 + y1) / 2, 0)\n wrapGeometries.push(seg)\n }\n const wrapMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(wrapGeometries), beltMaterial)\n wrapMesh.castShadow = true\n this.object3d.add(wrapMesh)\n }\n\n // Flat belt bottom (return path, slightly below)\n const bottomGeo = new THREE.BoxGeometry(flatLen, beltThickness, drumLength * 0.85)\n const bottomMesh = new THREE.Mesh(bottomGeo, beltMaterial)\n bottomMesh.position.set(0, beltY - drumRadius, 0)\n this.object3d.add(bottomMesh)\n }\n\n /** Control box (motor/controller housing) + status indicator light */\n private buildControlBox(\n width: number,\n height: number,\n depth: number,\n frameH: number,\n railW: number,\n value: number\n ) {\n const boxW = Math.max(width * 0.08, 4)\n const boxH = frameH * 0.7\n const boxD = Math.max(height * 0.2, 4)\n const railY = depth / 2 - frameH / 2\n\n // Box positioned at one end, attached to the side rail\n const boxMaterial = new THREE.MeshStandardMaterial({\n color: CONTROL_BOX_COLOR,\n metalness: 0.6,\n roughness: 0.4\n })\n\n const boxGeo = new THREE.BoxGeometry(boxW, boxH, boxD)\n const boxMesh = new THREE.Mesh(boxGeo, boxMaterial)\n boxMesh.position.set(\n -width / 2 + boxW / 2 + railW,\n railY - frameH / 2 - boxH / 2 + boxH * 0.15,\n -height / 2 + railW + boxD / 2\n )\n boxMesh.castShadow = true\n this.object3d.add(boxMesh)\n\n // Status indicator light on top of control box\n const lightR = Math.min(boxW, boxD) * 0.25\n const lightH = lightR * 1.2\n const emissiveColor = STATUS_EMISSIVE[value] ?? STATUS_EMISSIVE[0]\n const lightIntensity = value > 0 ? 1.5 : 0.2\n\n const lightMaterial = new THREE.MeshStandardMaterial({\n color: emissiveColor,\n emissive: emissiveColor,\n emissiveIntensity: lightIntensity,\n metalness: 0.0,\n roughness: 0.3\n })\n\n const lightGeo = new THREE.CylinderGeometry(lightR, lightR * 0.8, lightH, 12)\n const lightMesh = new THREE.Mesh(lightGeo, lightMaterial)\n lightMesh.position.set(\n boxMesh.position.x,\n boxMesh.position.y + boxH / 2 + lightH / 2,\n boxMesh.position.z\n )\n this.object3d.add(lightMesh)\n }\n\n updateDimension() {}\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if ('value' in after || 'conveyorType' in after || 'rollWidth' in after || 'width' in after || 'height' in after || 'depth' in after) {\n this.update()\n return\n }\n super.onchange(after, before)\n }\n\n updateAlpha() {}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"conveyor-3d.js","sourceRoot":"","sources":["../src/conveyor-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Straight Conveyor 3D Model\n *\n * Roller type: side rails + evenly-spaced cylindrical rollers + 4 legs with cross-bracing\n * Belt type: side rails + two end drums with belt wrapping over them + 4 legs with cross-bracing\n * Both types include a control box at one end and a status indicator light.\n */\n\nimport * as THREE from 'three'\nimport * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'\nimport { RealObjectGroup } from '@hatiolab/things-scene'\n\nconst FILL_COLORS: Record<number, number> = {\n 0: 0xcccccc, // IDLE\n 1: 0xafd0f1, // RUN\n 2: 0xafd0f1, // REVERSE\n 3: 0xffba00, // WARN\n 4: 0xe9746b // ERROR\n}\n\nconst FRAME_COLOR = 0x888899\nconst ROLLER_COLOR = 0xaaaabc\nconst CONTROL_BOX_COLOR = 0x556677\nconst STATUS_EMISSIVE: Record<number, number> = {\n 0: 0x333333,\n 1: 0x44aaff,\n 2: 0x44aaff,\n 3: 0xffaa00,\n 4: 0xff3333\n}\n\nexport class Conveyor3D extends RealObjectGroup {\n get effectiveDepth(): number {\n const { width, height, depth } = this.component.state\n return depth || Math.min(width, height) * 1.5\n }\n\n get position() {\n const { zPos = 0 } = this.component.state\n return {\n x: this.cx,\n y: zPos + this.effectiveDepth / 2,\n z: this.cy\n }\n }\n\n /**\n * syncFromObject3D 역변환 시 zPos 오프셋.\n * position.y = zPos + effectiveDepth/2 이므로, 역변환도 effectiveDepth/2를 빼야 한다.\n */\n protected get syncZPosOffset(): number {\n return this.effectiveDepth / 2\n }\n\n build() {\n super.build()\n\n const { width, height, conveyorType = 0, value = 0, rollWidth = 10, orientation } = this.component.state\n const depth = this.effectiveDepth\n\n // orientation: 'horizontal' = 이송 가로, 'vertical' = 이송 세로, '' = auto(긴 방향)\n const isVertical = orientation === 'vertical' ? true\n : orientation === 'horizontal' ? false\n : width < height\n\n // 프레임 두께: rollWidth(롤러 직경)와 동일 단위. 롤러를 감쌀 수 있어야 한다.\n const rollerDiameter = Math.max(rollWidth as number, 2)\n const frameH = rollerDiameter\n const legH = Math.max(depth - frameH, 0)\n const beltWidth = isVertical ? width : height\n const railW = Math.max(beltWidth * 0.06, 2)\n const legThickness = Math.max(railW * 0.8, 2)\n\n const frameMaterial = new THREE.MeshStandardMaterial({\n color: FRAME_COLOR,\n metalness: 0.85,\n roughness: 0.35\n })\n\n // --- Frame: side rails + legs + cross-bracing ---\n const frameGeometries: THREE.BufferGeometry[] = []\n const railY = depth / 2 - frameH / 2\n\n // Side rails — 이송 방향을 따라, 벨트 양측에 배치\n if (isVertical) {\n for (const xSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(railW, frameH, height)\n rail.translate(xSign * (width / 2 - railW / 2), railY, 0)\n frameGeometries.push(rail)\n }\n } else {\n for (const zSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(width, frameH, railW)\n rail.translate(0, railY, zSign * (height / 2 - railW / 2))\n frameGeometries.push(rail)\n }\n }\n\n // 4 legs at corners\n const legTopY = depth / 2 - frameH\n const legCenterY = legTopY - legH / 2\n const legXPos = isVertical ? (width / 2 - railW / 2) : (width / 2 - legThickness / 2)\n const legZPos = isVertical ? (height / 2 - legThickness / 2) : (height / 2 - railW / 2)\n\n for (const xSign of [-1, 1]) {\n for (const zSign of [-1, 1]) {\n const leg = new THREE.BoxGeometry(legThickness, legH, legThickness)\n leg.translate(xSign * legXPos, legCenterY, zSign * legZPos)\n frameGeometries.push(leg)\n }\n }\n\n // Cross-bracing\n const braceH = legThickness * 0.6\n const braceW = legThickness * 0.6\n const braceY = legTopY - legH * 0.35\n\n // 이송 방향 브레이스\n if (isVertical) {\n for (const xSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(braceW, braceH, height - legThickness)\n brace.translate(xSign * legXPos, braceY, 0)\n frameGeometries.push(brace)\n }\n } else {\n for (const zSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(width - legThickness, braceH, braceW)\n brace.translate(0, braceY, zSign * legZPos)\n frameGeometries.push(brace)\n }\n }\n\n // 벨트폭 방향 브레이스\n if (isVertical) {\n for (const zSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(width - railW, braceH, braceW)\n brace.translate(0, braceY, zSign * legZPos)\n frameGeometries.push(brace)\n }\n } else {\n for (const xSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(braceW, braceH, height - railW)\n brace.translate(xSign * legXPos, braceY, 0)\n frameGeometries.push(brace)\n }\n }\n\n const frameMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(frameGeometries), frameMaterial)\n frameMesh.castShadow = true\n frameMesh.receiveShadow = true\n this.object3d.add(frameMesh)\n\n // --- Rollers or Belt ---\n if (conveyorType === 1) {\n this.buildBelt(width, height, depth, frameH, railW, value, isVertical)\n } else {\n this.buildRollers(width, height, depth, frameH, railW, rollWidth as number, isVertical)\n }\n\n // --- Control box (motor housing at one end) ---\n this.buildControlBox(width, height, depth, frameH, railW, value, isVertical)\n }\n\n private buildRollers(width: number, height: number, depth: number, frameH: number, railW: number, rollWidth: number, isVertical: boolean = false) {\n const rollerRadius = Math.max(rollWidth / 2, 1)\n const diameter = rollerRadius * 2\n const step = diameter + 1\n const rollerY = depth / 2 - frameH / 2\n\n const rollerGeometries: THREE.BufferGeometry[] = []\n\n if (isVertical) {\n // 롤러 축 = X축(가로), 이송 방향 = Z축(세로)\n const rollerLength = width - railW * 2 - 0.5\n const count = Math.max(1, Math.floor(height / step))\n const totalSpan = (count - 1) * step\n const startZ = -totalSpan / 2\n\n for (let i = 0; i < count; i++) {\n const z = startZ + i * step\n const roller = new THREE.CylinderGeometry(rollerRadius, rollerRadius, rollerLength, 16)\n roller.rotateZ(Math.PI / 2)\n roller.translate(0, rollerY, z)\n rollerGeometries.push(roller)\n }\n } else {\n // 롤러 축 = Z축(세로), 이송 방향 = X축(가로)\n const rollerLength = height - railW * 2 - 0.5\n const count = Math.max(1, Math.floor(width / step))\n const totalSpan = (count - 1) * step\n const startX = -totalSpan / 2\n\n for (let i = 0; i < count; i++) {\n const x = startX + i * step\n const roller = new THREE.CylinderGeometry(rollerRadius, rollerRadius, rollerLength, 16)\n roller.rotateX(Math.PI / 2)\n roller.translate(x, rollerY, 0)\n rollerGeometries.push(roller)\n }\n }\n\n if (rollerGeometries.length > 0) {\n const rollerMesh = new THREE.Mesh(\n BufferGeometryUtils.mergeGeometries(rollerGeometries),\n new THREE.MeshStandardMaterial({ color: ROLLER_COLOR, metalness: 0.9, roughness: 0.2 })\n )\n rollerMesh.castShadow = true\n this.object3d.add(rollerMesh)\n }\n }\n\n private buildBelt(width: number, height: number, depth: number, frameH: number, railW: number, value: number, isVertical: boolean = false) {\n const drumRadius = frameH * 0.38\n const beltY = depth / 2 - frameH / 2\n const fillColor = FILL_COLORS[value] ?? FILL_COLORS[0]\n\n const transportLen = isVertical ? height : width\n const bw = isVertical ? width : height\n const drumLength = bw - railW * 2\n\n const rollerMaterial = new THREE.MeshStandardMaterial({\n color: ROLLER_COLOR,\n metalness: 0.9,\n roughness: 0.2\n })\n\n // Two end drums\n const drumGeometries: THREE.BufferGeometry[] = []\n const drumInset = drumRadius * 1.5\n const drum1 = -transportLen / 2 + drumInset\n const drum2 = transportLen / 2 - drumInset\n\n for (const dp of [drum1, drum2]) {\n const drum = new THREE.CylinderGeometry(drumRadius, drumRadius, drumLength, 16)\n if (isVertical) {\n drum.rotateZ(Math.PI / 2)\n drum.translate(0, beltY, dp)\n } else {\n drum.rotateX(Math.PI / 2)\n drum.translate(dp, beltY, 0)\n }\n drumGeometries.push(drum)\n }\n\n const drumMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(drumGeometries), rollerMaterial)\n drumMesh.castShadow = true\n this.object3d.add(drumMesh)\n\n // Belt surface: flat top + half-cylinder wraps around each drum end\n const beltThickness = drumRadius * 0.12\n const beltMaterial = new THREE.MeshStandardMaterial({\n color: fillColor,\n metalness: 0.0,\n roughness: 0.9\n })\n\n // Flat belt top surface spanning between drums\n const flatLen = drum2 - drum1\n const flatGeo = isVertical\n ? new THREE.BoxGeometry(drumLength, beltThickness, flatLen)\n : new THREE.BoxGeometry(flatLen, beltThickness, drumLength)\n const flatMesh = new THREE.Mesh(flatGeo, beltMaterial)\n flatMesh.position.set(0, beltY + drumRadius, 0)\n flatMesh.castShadow = true\n this.object3d.add(flatMesh)\n\n // Belt wrap around drums\n const wrapSegments = 12\n for (const [dp, angleStart] of [\n [drum1, Math.PI / 2],\n [drum2, -Math.PI / 2]\n ] as [number, number][]) {\n const wrapGeometries: THREE.BufferGeometry[] = []\n for (let i = 0; i < wrapSegments; i++) {\n const a0 = angleStart + (Math.PI * i) / wrapSegments\n const a1 = angleStart + (Math.PI * (i + 1)) / wrapSegments\n const r = drumRadius + beltThickness / 2\n\n const p0 = dp + Math.cos(a0) * r\n const y0 = beltY + Math.sin(a0) * r\n const p1 = dp + Math.cos(a1) * r\n const y1 = beltY + Math.sin(a1) * r\n\n const segLen = Math.sqrt((p1 - p0) ** 2 + (y1 - y0) ** 2) * 1.05\n const segAngle = Math.atan2(y1 - y0, p1 - p0)\n\n if (isVertical) {\n const seg = new THREE.BoxGeometry(drumLength, beltThickness, segLen)\n seg.rotateX(-segAngle)\n seg.translate(0, (y0 + y1) / 2, (p0 + p1) / 2)\n wrapGeometries.push(seg)\n } else {\n const seg = new THREE.BoxGeometry(segLen, beltThickness, drumLength)\n seg.rotateZ(segAngle)\n seg.translate((p0 + p1) / 2, (y0 + y1) / 2, 0)\n wrapGeometries.push(seg)\n }\n }\n const wrapMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(wrapGeometries), beltMaterial)\n wrapMesh.castShadow = true\n this.object3d.add(wrapMesh)\n }\n\n // Flat belt bottom (return path)\n const bottomGeo = isVertical\n ? new THREE.BoxGeometry(drumLength * 0.85, beltThickness, flatLen)\n : new THREE.BoxGeometry(flatLen, beltThickness, drumLength * 0.85)\n const bottomMesh = new THREE.Mesh(bottomGeo, beltMaterial)\n bottomMesh.position.set(0, beltY - drumRadius, 0)\n this.object3d.add(bottomMesh)\n }\n\n /** Control box (motor/controller housing) + status indicator light */\n private buildControlBox(\n width: number,\n height: number,\n depth: number,\n frameH: number,\n railW: number,\n value: number,\n isVertical: boolean = false\n ) {\n const bw = isVertical ? width : height\n const tl = isVertical ? height : width\n const boxW = Math.max(tl * 0.08, 4)\n const boxH = frameH * 0.7\n const boxD = Math.max(bw * 0.2, 4)\n const railY = depth / 2 - frameH / 2\n\n // Box positioned at one end, attached to the side rail\n const boxMaterial = new THREE.MeshStandardMaterial({\n color: CONTROL_BOX_COLOR,\n metalness: 0.6,\n roughness: 0.4\n })\n\n const boxGeo = isVertical\n ? new THREE.BoxGeometry(boxD, boxH, boxW)\n : new THREE.BoxGeometry(boxW, boxH, boxD)\n const boxMesh = new THREE.Mesh(boxGeo, boxMaterial)\n if (isVertical) {\n boxMesh.position.set(\n -width / 2 + railW + boxD / 2,\n railY - frameH / 2 - boxH / 2 + boxH * 0.15,\n -height / 2 + boxW / 2 + railW\n )\n } else {\n boxMesh.position.set(\n -width / 2 + boxW / 2 + railW,\n railY - frameH / 2 - boxH / 2 + boxH * 0.15,\n -height / 2 + railW + boxD / 2\n )\n }\n boxMesh.castShadow = true\n this.object3d.add(boxMesh)\n\n // Status indicator light on top of control box\n const lightR = Math.min(boxW, boxD) * 0.25\n const lightH = lightR * 1.2\n const emissiveColor = STATUS_EMISSIVE[value] ?? STATUS_EMISSIVE[0]\n const lightIntensity = value > 0 ? 1.5 : 0.2\n\n const lightMaterial = new THREE.MeshStandardMaterial({\n color: emissiveColor,\n emissive: emissiveColor,\n emissiveIntensity: lightIntensity,\n metalness: 0.0,\n roughness: 0.3\n })\n\n const lightGeo = new THREE.CylinderGeometry(lightR, lightR * 0.8, lightH, 12)\n const lightMesh = new THREE.Mesh(lightGeo, lightMaterial)\n lightMesh.position.set(\n boxMesh.position.x,\n boxMesh.position.y + boxH / 2 + lightH / 2,\n boxMesh.position.z\n )\n this.object3d.add(lightMesh)\n }\n\n updateDimension() {}\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if ('value' in after || 'conveyorType' in after || 'rollWidth' in after || 'orientation' in after || 'width' in after || 'height' in after || 'depth' in after) {\n this.update()\n return\n }\n super.onchange(after, before)\n }\n\n updateAlpha() {}\n}\n"]}
|
|
@@ -7,11 +7,10 @@ export declare class ConveyorJoin3D extends RealObjectGroup {
|
|
|
7
7
|
z: number;
|
|
8
8
|
};
|
|
9
9
|
build(): void;
|
|
10
|
+
private addBrace;
|
|
10
11
|
private buildArcRail;
|
|
11
|
-
private arcPoint;
|
|
12
12
|
private buildRollers;
|
|
13
13
|
private buildBelt;
|
|
14
|
-
/** Control box + status light positioned at outer edge near start angle */
|
|
15
14
|
private buildControlBox;
|
|
16
15
|
updateDimension(): void;
|
|
17
16
|
onchange(after: Record<string, unknown>, before: Record<string, unknown>): void;
|