@operato/scene-transport 10.0.0-beta.25 → 10.0.0-beta.26

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/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [10.0.0-beta.26](https://github.com/things-scene/operato-scene/compare/v10.0.0-beta.25...v10.0.0-beta.26) (2026-05-03)
7
+
8
+
9
+ ### :bug: Bug Fix
10
+
11
+ * **forklift-3d:** symmetric fork placement (was shifted +forkW) ([db67e69](https://github.com/things-scene/operato-scene/commit/db67e69b125c766a660e14e8245231f6062e5ecd))
12
+
13
+
14
+
6
15
  ## [10.0.0-beta.25](https://github.com/things-scene/operato-scene/compare/v10.0.0-beta.24...v10.0.0-beta.25) (2026-05-03)
7
16
 
8
17
  **Note:** Version bump only for package @operato/scene-transport
@@ -420,7 +420,12 @@ export class Forklift3D extends RealObjectGroup {
420
420
  });
421
421
  // rotateY(+π/2): fork shape +X (blade tip) → world -Z (forward).
422
422
  forkGeo.rotateY(Math.PI / 2);
423
- forkGeo.translate(xSign * mastSpacing * 0.45 + forkW / 2, forkBladeY, mastZ - mastRailD - carriageD // heel forward of carriage (-Z)
423
+ // ExtrudeGeometry depth +Z 방향으로 자라고, rotateY(π/2) +X 방향.
424
+ // 즉 fork 의 local origin (translate 적용점) 은 fork 의 LEFT 모서리. fork 중심은
425
+ // origin + forkW/2. 좌우 대칭으로 배치하려면 중심을 xSign * mastSpacing * 0.45
426
+ // 에 두어야 하므로 translate.x = xSign * 0.45 - forkW/2. 기존엔 +forkW/2 라서
427
+ // 양쪽 fork 가 동일 방향으로 forkW 만큼 쏠려있던 버그.
428
+ forkGeo.translate(xSign * mastSpacing * 0.45 - forkW / 2, forkBladeY, mastZ - mastRailD - carriageD // heel forward of carriage (-Z)
424
429
  );
425
430
  const forkMesh = new THREE.Mesh(forkGeo, forkMat);
426
431
  forkMesh.castShadow = true;
@@ -1 +1 @@
1
- {"version":3,"file":"forklift-3d.js","sourceRoot":"","sources":["../src/forklift-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Forklift 3D — designed from a real forklift's proportions, not stacked from\n * primitive geometry. Procedural lo-poly with deliberate aesthetic choices.\n *\n * Design priorities (in order):\n *\n * 1. **Silhouette reads** — at any camera angle the mast + counterweight +\n * forks combo identifies this as an industrial forklift.\n * 2. **Proportions** — chassis ~35% of envelope, cab ~25%, overhead guard\n * ~30%. Forks extend forward roughly the full chassis length.\n * Counterweight is the heaviest visual mass, set rearward.\n * 3. **Sculpted, not stacked** — the chassis side profile is a single\n * `ExtrudeGeometry` (sloped hood / cab indent / counterweight rise),\n * not three separate boxes glued together. Mast and forks are\n * L-shaped extrusions, not rectangular prisms.\n * 4. **Material palette** — yellow body with subtle shaded variant for\n * shape-reading; dark counterweight; cool gray mast; chrome hydraulic.\n * Status emissive only on the lamp + accent stripe.\n * 5. **Sub-assemblies as groups** — chassis / cab / guard / mast / wheels\n * / accents are organized as scene-graph children. Adjustable mass\n * (mast group, forks) tracks `state.forkHeight` cleanly.\n *\n * Coordinate convention (component-local):\n * - Origin at the geometric center of the component bounds.\n * - X-axis: vehicle width (left/right).\n * - Y-axis: vertical. Floor at `-depth/2`, ceiling at `+depth/2`.\n * - Z-axis: vehicle length, **-Z = forward** (forks point this way).\n * This matches things-scene's vehicle convention (rotation=0 → -Z\n * forward, equivalent to \"default toward canvas top edge\"). The\n * Waypoint animation's `yawOffset = π/2` (default) lines up the\n * travel heading with this axis without any extra correction.\n *\n * Defaults (with the scene-unit StandardHeights — operation=50, ceiling=200):\n * - depth = 200 (full envelope; mast collapsed reaches ~80%, mast up to top)\n * - wheelR = depth * 0.07 (~14)\n * - chassis section length ~0.65 of width footprint\n * - cab seat height ~operation level (matches the design intuition that\n * the operator's seat sits at the standard operation surface)\n */\n\nimport * as THREE from 'three'\nimport * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'\nimport { RoundedBoxGeometry } from 'three/examples/jsm/geometries/RoundedBoxGeometry.js'\nimport { RealObjectGroup } from '@hatiolab/things-scene'\n\n// ─── Color palette ─────────────────────────────────────────────────────────\n// counterweight 는 본체 어두운 음영 (bodyShadeMat 사용 — body 색 * 0.5).\nconst COLOR_MAST = 0x36363f\nconst COLOR_FORK = 0xb8bcc4 // silver/light gray (레퍼런스)\nconst COLOR_TIRE = 0x171719\nconst COLOR_RIM = 0x707080\nconst COLOR_HUB = 0xb8b8c0\nconst COLOR_SEAT = 0x14141c\nconst COLOR_STEERING = 0x202028\nconst COLOR_GUARD = 0x252530\nconst COLOR_ROOF = 0xa8acb4 // 운전석 지붕 (실버)\nconst COLOR_HYDRAULIC = 0xc8ccd8\nconst COLOR_CHAIN = 0x4a4a55\nconst COLOR_WINDOW = 0x88aacc\nconst COLOR_TAIL = 0xff2626\nconst COLOR_HEADLIGHT = 0xfff7d4\n\nexport class Forklift3D extends RealObjectGroup {\n /**\n * Inner group that holds the actual mesh tree. Rotated π around Y so\n * the procedural model (drawn with forks pointing along component-local\n * +Z) aligns with things-scene's vehicle convention of -Z forward.\n *\n * Carriers attach onto this group (not `object3d`) so they inherit the\n * same rotation as the visible mesh — `cargoMount` coordinates remain\n * authored in the model's natural +Z-forward frame and the wrapper\n * transforms them to match the visible forks.\n */\n private _modelGroup?: THREE.Group\n\n get modelGroup(): THREE.Group | undefined {\n return this._modelGroup\n }\n\n /** Local-frame (-Z forward) fork-tip top surface — where cargo sits. */\n get cargoMount(): { x: number; y: number; z: number; width: number; depth: number } {\n const { width, height, depth = 200 } = this.component.state\n const raw = (this.component.state.forkHeight as number) ?? 0\n const forkHeight = Math.max(0, Math.min(raw, depth * 0.85))\n const wheelR = depth * 0.07\n const forkH = depth * 0.018\n const forkLen = height * 0.42\n const y = -depth / 2 + wheelR + forkHeight + forkH\n const z = -(height * 0.42 + forkLen / 2) // forks point -Z\n return { x: 0, y, z, width: width * 0.4, depth: forkLen }\n }\n\n build() {\n super.build()\n\n // ── State + clamping ─────────────────────────────────────────────\n const { width, height } = this.component.state\n // Resolve depth via the NaN-safe getter so a freshly-created Forklift\n // (template doesn't carry `depth`; Placeable.added writes it via setState\n // which races with the first build) renders with the Placeable archetype\n // default instead of a hard-coded fallback. The hard-coded value was\n // visually wrong-sized on the first frame and only \"snapped\" to a normal\n // shape after a 3D mode re-entry triggered a fresh build.\n const depth = this.effectiveDepth\n const bodyColor = (this.component.state.bodyColor as string) || '#ffc107'\n const lampEmissive = (this.component.state.lampEmissive as string) || '#333333'\n const status = this.component.state.status\n const lampIntensity = status && status !== 'idle' ? 1.5 : 0.2\n const forkHeightRaw = (this.component.state.forkHeight as number) ?? 0\n const forkHeight = Math.max(0, Math.min(forkHeightRaw, depth * 0.85))\n\n // ── Proportions (볼륨감 강화) ─────────────────────────────────────\n const baseY = -depth / 2\n const wheelR = depth * 0.14 // 더 큰 휠로 무거운 산업차량 느낌\n const chassisH = depth * 0.38 // 더 두툼한 본체\n const cabH = depth * 0.22\n const guardH = depth * 0.28\n const cwH = depth * 0.62 // counterweight 더 높이 키워 후방 매스감 확보\n const cwD = height * 0.28 // counterweight 더 깊게\n const chassisLen = height * 0.62 // 본체 길이 키움\n const chassisExtrudeW = width * 0.88 // 본체 폭 키움 (이전 0.78)\n const cabFloorY = baseY + wheelR + chassisH * 0.85\n\n // ── Materials (매트한 painted look — 레퍼런스 일관성) ────────────\n const bodyMat = new THREE.MeshStandardMaterial({\n color: bodyColor,\n metalness: 0.0,\n roughness: 0.65\n })\n const bodyShadeMat = new THREE.MeshStandardMaterial({\n color: new THREE.Color(bodyColor).multiplyScalar(0.72),\n metalness: 0.0,\n roughness: 0.65\n })\n // counterweight — 본체와 같은 색 (레퍼런스: 통합된 한 덩어리 느낌).\n const cwMat = bodyMat\n const mastMat = new THREE.MeshStandardMaterial({\n color: COLOR_MAST,\n metalness: 0.10,\n roughness: 0.65\n })\n const forkMat = new THREE.MeshStandardMaterial({\n color: COLOR_FORK,\n metalness: 0.20,\n roughness: 0.55\n })\n const tireMat = new THREE.MeshStandardMaterial({ color: COLOR_TIRE, roughness: 0.95 })\n const rimMat = new THREE.MeshStandardMaterial({ color: COLOR_RIM, metalness: 0.80, roughness: 0.30 })\n const hubMat = new THREE.MeshStandardMaterial({ color: COLOR_HUB, metalness: 0.85, roughness: 0.25 })\n const seatMat = new THREE.MeshStandardMaterial({ color: COLOR_SEAT, roughness: 0.85 })\n const guardMat = new THREE.MeshStandardMaterial({ color: COLOR_GUARD, metalness: 0.75, roughness: 0.40 })\n const hydraulicMat = new THREE.MeshStandardMaterial({ color: COLOR_HYDRAULIC, metalness: 0.95, roughness: 0.10 })\n const chainMat = new THREE.MeshStandardMaterial({ color: COLOR_CHAIN, metalness: 0.80, roughness: 0.40 })\n const windowMat = new THREE.MeshStandardMaterial({\n color: COLOR_WINDOW, metalness: 0.20, roughness: 0.05,\n transparent: true, opacity: 0.55\n })\n const tailMat = new THREE.MeshStandardMaterial({\n color: COLOR_TAIL, emissive: COLOR_TAIL, emissiveIntensity: 0.6,\n metalness: 0.10, roughness: 0.40\n })\n const headlightMat = new THREE.MeshStandardMaterial({\n color: COLOR_HEADLIGHT, emissive: COLOR_HEADLIGHT, emissiveIntensity: 0.4,\n metalness: 0.10, roughness: 0.30\n })\n\n // ────────────────────────────────────────────────────────────────\n // 1. CHASSIS BODY — sculpted side profile + width via ExtrudeGeometry\n // ────────────────────────────────────────────────────────────────\n const chassisGroup = new THREE.Group()\n chassisGroup.position.set(0, baseY + wheelR, 0) // wheels rest on floor\n\n // Side profile (looking from +X, **-Z forward**, +Y up).\n // sideShape's first axis is the vehicle length axis (+X = front, -X = back).\n // `rotateY(+π/2)` maps sideShape's +X to world -Z (= forward), giving the\n // -Z-forward convention. (Earlier the chassis used the same +π/2 mapping,\n // i.e. it was already -Z-forward; the rest of the model used z-direct\n // positions in the OPPOSITE sign convention. Aligning the rest to -Z\n // forward — by sign-flipping the direct z coords elsewhere — left the\n // chassis untouched as the canonical -Z-forward part.)\n const zFront = chassisLen * 0.5\n const zBack = -chassisLen * 0.5\n const hoodH = chassisH * 0.55\n const stepZ = chassisLen * 0.10\n const seatH = chassisH * 0.85\n\n const sideShape = new THREE.Shape()\n sideShape.moveTo(zFront, 0)\n sideShape.lineTo(zFront, hoodH) // up to hood top\n sideShape.lineTo(stepZ * 1.2, hoodH) // forward hood flat\n sideShape.lineTo(stepZ * 0.4, seatH) // sloped step up to seat platform\n sideShape.lineTo(zBack + stepZ, seatH) // platform flat to rear\n sideShape.lineTo(zBack, seatH * 1.05) // tiny lip into counterweight\n sideShape.lineTo(zBack, 0) // down to ground\n sideShape.lineTo(zFront, 0)\n\n const chassisGeo = new THREE.ExtrudeGeometry(sideShape, {\n depth: chassisExtrudeW,\n bevelEnabled: true,\n bevelSegments: 2,\n bevelSize: chassisH * 0.04,\n bevelThickness: chassisH * 0.04,\n curveSegments: 6\n })\n // rotateY(+π/2): sideShape +X (front) → world -Z (forward).\n // After rotateY(+π/2), extrude depth (sideShape +Z) → world +X.\n // depth range [0, extrudeW] → world X range [0, extrudeW]. Centred via\n // translate(-extrudeW/2). Wait — that's wrong for [0, extrudeW]; let\n // me recompute explicitly:\n // rotateY(+π/2): (x,y,z) → (z, y, -x)\n // ExtrudeGeometry produces verts with z in [0, depth]; after rotation\n // their X component = original Z, so X range [0, depth]. Translating\n // X by -depth/2 centres at 0. ✓\n chassisGeo.rotateY(Math.PI / 2)\n chassisGeo.translate(-chassisExtrudeW / 2, 0, 0)\n const chassisMesh = new THREE.Mesh(chassisGeo, bodyMat)\n chassisMesh.castShadow = true\n chassisMesh.receiveShadow = true\n chassisGroup.add(chassisMesh)\n\n this.object3d.add(chassisGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 2. COUNTERWEIGHT — sculpted rear mass (tapered, distinct from chassis)\n // ────────────────────────────────────────────────────────────────\n const cwGroup = new THREE.Group()\n // counterweight in world: back of vehicle = +Z (since -Z is forward).\n const cwZ = -zBack + cwD * 0.5\n\n // Base — wide, rectangular with rounded corners, sits low\n const cwBaseGeo = new RoundedBoxGeometry(width * 0.96, cwH * 0.70, cwD, 3, cwH * 0.05)\n const cwBaseMesh = new THREE.Mesh(cwBaseGeo, cwMat)\n cwBaseMesh.position.set(0, baseY + wheelR + cwH * 0.35, cwZ)\n cwBaseMesh.castShadow = true\n cwGroup.add(cwBaseMesh)\n\n // Top — narrower, slightly forward — gives the chamfered cast-iron look\n const cwTopGeo = new RoundedBoxGeometry(width * 0.82, cwH * 0.32, cwD * 0.85, 3, cwH * 0.04)\n const cwTopMat = new THREE.MeshStandardMaterial({\n color: new THREE.Color(bodyColor).multiplyScalar(0.65),\n metalness: 0.30, roughness: 0.55\n })\n const cwTopMesh = new THREE.Mesh(cwTopGeo, cwTopMat)\n cwTopMesh.position.set(0, baseY + wheelR + cwH * 0.70 + cwH * 0.16, cwZ + cwD * 0.05)\n cwTopMesh.castShadow = true\n cwGroup.add(cwTopMesh)\n\n this.object3d.add(cwGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 3. CAB — open frame: pillars + roof + seat + steering\n // ────────────────────────────────────────────────────────────────\n const cabGroup = new THREE.Group()\n const cabRoofY = cabFloorY + cabH\n const pillarT = width * 0.025\n const pillarPositions: [number, number][] = [\n [width * 0.27, -height * 0.05], // front-right (front = -Z)\n [width * 0.27, height * 0.28], // rear-right (rear = +Z)\n [-width * 0.27, -height * 0.05],\n [-width * 0.27, height * 0.28]\n ]\n\n const pillarGeos: THREE.BufferGeometry[] = []\n for (const [x, z] of pillarPositions) {\n const g = new RoundedBoxGeometry(pillarT, cabH, pillarT, 1, pillarT * 0.2)\n g.translate(x, cabFloorY + cabH / 2, z)\n pillarGeos.push(g)\n }\n const pillarsMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(pillarGeos), bodyShadeMat)\n pillarsMesh.castShadow = true\n cabGroup.add(pillarsMesh)\n\n // Operator seat (간단히 좌석 + 등받이만)\n const seatGeo = new RoundedBoxGeometry(width * 0.28, cabH * 0.40, height * 0.20, 2, width * 0.03)\n const seatMesh = new THREE.Mesh(seatGeo, seatMat)\n seatMesh.position.set(0, cabFloorY + cabH * 0.22, height * 0.18) // seat at rear of cab\n cabGroup.add(seatMesh)\n\n const backGeo = new RoundedBoxGeometry(width * 0.28, cabH * 0.65, height * 0.04, 2, width * 0.02)\n const backMesh = new THREE.Mesh(backGeo, seatMat)\n backMesh.position.set(0, cabFloorY + cabH * 0.55, height * 0.27) // backrest behind seat\n cabGroup.add(backMesh)\n\n // Steering wheel — 운전석 앞에 작은 검정 링 (식별성).\n const steeringMat = new THREE.MeshStandardMaterial({\n color: COLOR_STEERING, metalness: 0.4, roughness: 0.55\n })\n const colGeo = new THREE.CylinderGeometry(width * 0.014, width * 0.020, cabH * 0.45, 12)\n colGeo.rotateX(-Math.PI * 0.12)\n const colMesh = new THREE.Mesh(colGeo, steeringMat)\n colMesh.position.set(0, cabFloorY + cabH * 0.27, height * 0.05) // forward of seat (toward forks = -Z, but column is in front of seat which is at +0.18)\n cabGroup.add(colMesh)\n const swGeo = new THREE.TorusGeometry(width * 0.10, width * 0.013, 6, 18)\n swGeo.rotateX(Math.PI / 2 - Math.PI * 0.12)\n const swMesh = new THREE.Mesh(swGeo, steeringMat)\n swMesh.position.set(0, cabFloorY + cabH * 0.50, -height * 0.01) // wheel slightly forward of column\n cabGroup.add(swMesh)\n\n this.object3d.add(cabGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 4. OVERHEAD GUARD — ROPS structure above cab\n // ────────────────────────────────────────────────────────────────\n const guardGroup = new THREE.Group()\n const guardPostT = width * 0.024\n const guardX = width * 0.27\n const guardZF = -height * 0.05 // front of guard at -Z\n const guardZB = height * 0.38 // rear of guard at +Z\n const guardPostY = cabRoofY + guardH / 2\n\n const guardGeos: THREE.BufferGeometry[] = []\n for (const xSign of [-1, 1]) {\n for (const z of [guardZF, guardZB]) {\n const g = new THREE.BoxGeometry(guardPostT, guardH, guardPostT)\n g.translate(xSign * guardX, guardPostY, z)\n guardGeos.push(g)\n }\n }\n // Roof grid (3 lateral + 3 longitudinal bars)\n const roofY = guardPostY + guardH / 2 + guardPostT / 2\n // Span is positive (guardZB is rear/+Z, guardZF is front/-Z, rear − front).\n const roofZSpan = guardZB - guardZF\n for (const xFrac of [-1, 0, 1]) {\n const g = new THREE.BoxGeometry(guardPostT * 0.7, guardPostT * 0.7, roofZSpan + guardPostT)\n g.translate(xFrac * guardX, roofY, (guardZF + guardZB) / 2)\n guardGeos.push(g)\n }\n for (const zFrac of [-1, 0, 1]) {\n const g = new THREE.BoxGeometry(2 * guardX + guardPostT, guardPostT * 0.7, guardPostT * 0.7)\n g.translate(0, roofY, (guardZF + guardZB) / 2 + zFrac * roofZSpan * 0.5)\n guardGeos.push(g)\n }\n const guardMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(guardGeos), guardMat)\n guardMesh.castShadow = true\n guardGroup.add(guardMesh)\n\n // Roof panel — 솔리드 그레이 (레퍼런스 일관성).\n const roofPanelMat = new THREE.MeshStandardMaterial({\n color: COLOR_ROOF, metalness: 0.25, roughness: 0.55\n })\n const roofPanelW = 2 * guardX + guardPostT * 1.2\n const roofPanelD = guardZB - guardZF + guardPostT * 1.2\n const roofPanelGeo = new RoundedBoxGeometry(roofPanelW, depth * 0.025, roofPanelD, 2, depth * 0.012)\n const roofPanelMesh = new THREE.Mesh(roofPanelGeo, roofPanelMat)\n roofPanelMesh.position.set(0, roofY + depth * 0.012, (guardZF + guardZB) / 2)\n roofPanelMesh.castShadow = true\n guardGroup.add(roofPanelMesh)\n\n this.object3d.add(guardGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 5. MAST ASSEMBLY — rails + crossbar + hydraulic + chains + carriage + forks\n // ────────────────────────────────────────────────────────────────\n const mastGroup = new THREE.Group()\n const mastH = depth * 0.95\n const mastRailW = width * 0.06\n const mastRailD = height * 0.03\n const mastSpacing = width * 0.45\n // chassis front is now at -Z (forward); mast attaches just ahead.\n const mastZ = -(chassisLen / 2 + mastRailD)\n const mastY = baseY + wheelR + mastH / 2\n\n // Two main rails (rounded for visual softness)\n for (const xSign of [-1, 1]) {\n const railGeo = new RoundedBoxGeometry(mastRailW, mastH, mastRailD, 2, mastRailW * 0.20)\n const railMesh = new THREE.Mesh(railGeo, mastMat)\n railMesh.position.set((xSign * mastSpacing) / 2, mastY, mastZ)\n railMesh.castShadow = true\n mastGroup.add(railMesh)\n }\n\n // Crossbar at top\n const crossbarGeo = new RoundedBoxGeometry(\n mastSpacing + mastRailW, mastRailD * 1.3, mastRailD * 1.1, 2, mastRailW * 0.15\n )\n const crossbarMesh = new THREE.Mesh(crossbarGeo, mastMat)\n crossbarMesh.position.set(0, baseY + wheelR + mastH, mastZ)\n crossbarMesh.castShadow = true\n mastGroup.add(crossbarMesh)\n\n // Hydraulic cylinder (center, between rails)\n const hydCylR = mastRailW * 0.42\n const hydCylH = mastH * 0.78\n const hydCylGeo = new THREE.CylinderGeometry(hydCylR, hydCylR * 1.05, hydCylH, 20)\n const hydCylMesh = new THREE.Mesh(hydCylGeo, hydraulicMat)\n hydCylMesh.position.set(0, baseY + wheelR + hydCylH / 2 + mastRailD * 0.5, mastZ + mastRailD * 0.15) // hydraulic behind mast (+Z = back)\n hydCylMesh.castShadow = true\n mastGroup.add(hydCylMesh)\n\n // Piston rod (length tracks forkHeight)\n const pistonR = hydCylR * 0.55\n const pistonH = hydCylH * 0.45 + forkHeight * 0.7\n const pistonGeo = new THREE.CylinderGeometry(pistonR, pistonR, pistonH, 16)\n const pistonMesh = new THREE.Mesh(pistonGeo, hydraulicMat)\n pistonMesh.position.set(\n 0,\n baseY + wheelR + hydCylH + pistonH / 2 + mastRailD * 0.5,\n mastZ + mastRailD * 0.15 // piston behind mast (+Z)\n )\n mastGroup.add(pistonMesh)\n\n // Carriage (sliding plate) + load backrest grid\n const carriageY = baseY + wheelR + forkHeight + cwH * 0.05\n const carriageW = mastSpacing + mastRailW\n const carriageH = chassisH * 0.40\n const carriageD = mastRailD * 0.7\n const carriageGeo = new RoundedBoxGeometry(carriageW, carriageH, carriageD, 2, carriageH * 0.10)\n const carriageMesh = new THREE.Mesh(carriageGeo, forkMat)\n carriageMesh.position.set(0, carriageY + carriageH / 2, mastZ - mastRailD) // carriage forward of mast (-Z)\n carriageMesh.castShadow = true\n mastGroup.add(carriageMesh)\n\n // Load backrest — carriage 위로 수직 슬랫 그리드 (하중 받침 케이지).\n // 레퍼런스의 distinctive feature: 적재물이 운전자 쪽으로 넘어오지 않게 막는 격자.\n const backrestH = carriageH * 1.6\n const backrestY = carriageY + carriageH + backrestH / 2\n const backrestZ = mastZ - mastRailD // backrest forward of mast (-Z)\n const slatT = mastRailD * 0.5\n const slatGeos: THREE.BufferGeometry[] = []\n // 5 vertical slats\n for (let i = 0; i < 5; i++) {\n const t = i / 4\n const slatX = -carriageW / 2 + carriageH * 0.15 + t * (carriageW - carriageH * 0.30)\n const sg = new THREE.BoxGeometry(slatT, backrestH, slatT)\n sg.translate(slatX, backrestY, backrestZ)\n slatGeos.push(sg)\n }\n // Top + bottom rails connecting the slats\n for (const ySign of [-1, 1]) {\n const rg = new THREE.BoxGeometry(carriageW * 0.92, slatT, slatT)\n rg.translate(0, backrestY + ySign * (backrestH / 2 - slatT / 2), backrestZ)\n slatGeos.push(rg)\n }\n const backrestMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(slatGeos), forkMat)\n backrestMesh.castShadow = true\n mastGroup.add(backrestMesh)\n\n // Forks (L-shape via ExtrudeGeometry — heel + horizontal blade)\n const forkLen = height * 0.42\n const forkW = width * 0.10\n const forkH = depth * 0.018\n const forkBladeY = carriageY + forkH / 2\n for (const xSign of [-1, 1]) {\n const heelH = carriageH * 0.85\n const fs = new THREE.Shape()\n fs.moveTo(0, 0)\n fs.lineTo(forkLen, 0)\n fs.lineTo(forkLen, forkH * 0.5)\n fs.lineTo(forkH, forkH * 1.0)\n fs.lineTo(forkH, heelH)\n fs.lineTo(0, heelH)\n fs.lineTo(0, 0)\n const forkGeo = new THREE.ExtrudeGeometry(fs, {\n depth: forkW,\n bevelEnabled: true,\n bevelSegments: 1,\n bevelSize: forkH * 0.18,\n bevelThickness: forkH * 0.18\n })\n // rotateY(+π/2): fork shape +X (blade tip) → world -Z (forward).\n forkGeo.rotateY(Math.PI / 2)\n forkGeo.translate(\n xSign * mastSpacing * 0.45 + forkW / 2,\n forkBladeY,\n mastZ - mastRailD - carriageD // heel forward of carriage (-Z)\n )\n const forkMesh = new THREE.Mesh(forkGeo, forkMat)\n forkMesh.castShadow = true\n mastGroup.add(forkMesh)\n }\n\n this.object3d.add(mastGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 6. WHEELS — tire + rim disc + spokes (drive front, caster rear)\n // ────────────────────────────────────────────────────────────────\n const wheelW = depth * 0.04\n const wheelGroup = new THREE.Group()\n\n const tireGeos: THREE.BufferGeometry[] = []\n const rimGeos: THREE.BufferGeometry[] = []\n const hubGeos: THREE.BufferGeometry[] = []\n\n // Front (drive) wheels — slightly larger. Front of vehicle is -Z.\n for (const xSign of [-1, 1]) {\n const cx = xSign * width * 0.42\n const cz = -height * 0.30\n const r = wheelR * 1.05\n\n const tire = new THREE.CylinderGeometry(r, r, wheelW, 24)\n tire.rotateZ(Math.PI / 2)\n tire.translate(cx, baseY + r, cz)\n tireGeos.push(tire)\n\n const rim = new THREE.CylinderGeometry(r * 0.55, r * 0.55, wheelW * 0.85, 18)\n rim.rotateZ(Math.PI / 2)\n rim.translate(cx + xSign * wheelW * 0.10, baseY + r, cz)\n rimGeos.push(rim)\n }\n\n // Rear (caster) wheels — smaller. Rear of vehicle is +Z.\n for (const xSign of [-1, 1]) {\n const cx = xSign * width * 0.36\n const cz = height * 0.32\n const r = wheelR * 0.78\n\n const tire = new THREE.CylinderGeometry(r, r, wheelW * 0.85, 20)\n tire.rotateZ(Math.PI / 2)\n tire.translate(cx, baseY + r, cz)\n tireGeos.push(tire)\n\n const rim = new THREE.CylinderGeometry(r * 0.55, r * 0.55, wheelW * 0.7, 16)\n rim.rotateZ(Math.PI / 2)\n rim.translate(cx + xSign * wheelW * 0.08, baseY + r, cz)\n rimGeos.push(rim)\n }\n\n const tireMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(tireGeos), tireMat)\n tireMesh.castShadow = true\n wheelGroup.add(tireMesh)\n\n const rimMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(rimGeos), rimMat)\n rimMesh.castShadow = true\n wheelGroup.add(rimMesh)\n\n if (hubGeos.length > 0) {\n const hubMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(hubGeos), hubMat)\n wheelGroup.add(hubMesh)\n }\n\n this.object3d.add(wheelGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 7. STATUS LAMP — sculpted (base + body + dome) on guard top\n // ────────────────────────────────────────────────────────────────\n const lampGroup = new THREE.Group()\n const lampR = Math.min(width, height) * 0.04\n const lampH = lampR * 1.5\n const lampMat = new THREE.MeshStandardMaterial({\n color: lampEmissive, emissive: lampEmissive,\n emissiveIntensity: lampIntensity,\n metalness: 0.0, roughness: 0.30\n })\n\n // Base disc\n const lbGeo = new THREE.CylinderGeometry(lampR * 1.15, lampR * 1.15, lampR * 0.25, 16)\n const lbMesh = new THREE.Mesh(lbGeo, guardMat)\n lbMesh.position.set(0, roofY + guardPostT * 0.5 + lampR * 0.125, (guardZF + guardZB) / 2)\n lampGroup.add(lbMesh)\n\n // Body\n const lyGeo = new THREE.CylinderGeometry(lampR, lampR * 0.95, lampH, 16)\n const lyMesh = new THREE.Mesh(lyGeo, lampMat)\n lyMesh.position.set(0, roofY + guardPostT * 0.5 + lampR * 0.25 + lampH / 2, (guardZF + guardZB) / 2)\n lampGroup.add(lyMesh)\n\n // Dome\n const ldGeo = new THREE.SphereGeometry(lampR, 16, 8, 0, Math.PI * 2, 0, Math.PI / 2)\n const ldMesh = new THREE.Mesh(ldGeo, lampMat)\n ldMesh.position.set(0, roofY + guardPostT * 0.5 + lampR * 0.25 + lampH, (guardZF + guardZB) / 2)\n lampGroup.add(ldMesh)\n\n this.object3d.add(lampGroup)\n\n // NOTE: model is drawn with forks pointing along component-local +Z.\n // This is the natural authoring axis but doesn't match things-scene's\n // vehicle convention of -Z forward — meaning the visible heading is\n // 180° off the travel heading set by Waypoint.\n //\n // Earlier we wrapped all children in an inner Group rotated π to fix\n // this without rewriting geometry. That wrap collided with reparent:\n // every build() rebuilt the wrap from scratch, which dropped attached\n // carriers. Removed.\n //\n // Direction fix is deferred — proper resolution is rewriting the mesh\n // coordinates with forks along -Z (or applying yaw at the model level\n // in a way `clear()`/`build()` doesn't undo). Until then, the forklift\n // visually points opposite to its travel direction; reparent works\n // correctly though.\n }\n\n updateDimension() {}\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if (\n 'status' in after ||\n 'bodyColor' in after ||\n 'lampEmissive' in after ||\n 'forkHeight' in after ||\n 'width' in after ||\n 'height' in after ||\n 'depth' in after\n ) {\n this.update()\n return\n }\n super.onchange(after, before)\n }\n\n updateAlpha() {}\n}\n"]}
1
+ {"version":3,"file":"forklift-3d.js","sourceRoot":"","sources":["../src/forklift-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Forklift 3D — designed from a real forklift's proportions, not stacked from\n * primitive geometry. Procedural lo-poly with deliberate aesthetic choices.\n *\n * Design priorities (in order):\n *\n * 1. **Silhouette reads** — at any camera angle the mast + counterweight +\n * forks combo identifies this as an industrial forklift.\n * 2. **Proportions** — chassis ~35% of envelope, cab ~25%, overhead guard\n * ~30%. Forks extend forward roughly the full chassis length.\n * Counterweight is the heaviest visual mass, set rearward.\n * 3. **Sculpted, not stacked** — the chassis side profile is a single\n * `ExtrudeGeometry` (sloped hood / cab indent / counterweight rise),\n * not three separate boxes glued together. Mast and forks are\n * L-shaped extrusions, not rectangular prisms.\n * 4. **Material palette** — yellow body with subtle shaded variant for\n * shape-reading; dark counterweight; cool gray mast; chrome hydraulic.\n * Status emissive only on the lamp + accent stripe.\n * 5. **Sub-assemblies as groups** — chassis / cab / guard / mast / wheels\n * / accents are organized as scene-graph children. Adjustable mass\n * (mast group, forks) tracks `state.forkHeight` cleanly.\n *\n * Coordinate convention (component-local):\n * - Origin at the geometric center of the component bounds.\n * - X-axis: vehicle width (left/right).\n * - Y-axis: vertical. Floor at `-depth/2`, ceiling at `+depth/2`.\n * - Z-axis: vehicle length, **-Z = forward** (forks point this way).\n * This matches things-scene's vehicle convention (rotation=0 → -Z\n * forward, equivalent to \"default toward canvas top edge\"). The\n * Waypoint animation's `yawOffset = π/2` (default) lines up the\n * travel heading with this axis without any extra correction.\n *\n * Defaults (with the scene-unit StandardHeights — operation=50, ceiling=200):\n * - depth = 200 (full envelope; mast collapsed reaches ~80%, mast up to top)\n * - wheelR = depth * 0.07 (~14)\n * - chassis section length ~0.65 of width footprint\n * - cab seat height ~operation level (matches the design intuition that\n * the operator's seat sits at the standard operation surface)\n */\n\nimport * as THREE from 'three'\nimport * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'\nimport { RoundedBoxGeometry } from 'three/examples/jsm/geometries/RoundedBoxGeometry.js'\nimport { RealObjectGroup } from '@hatiolab/things-scene'\n\n// ─── Color palette ─────────────────────────────────────────────────────────\n// counterweight 는 본체 어두운 음영 (bodyShadeMat 사용 — body 색 * 0.5).\nconst COLOR_MAST = 0x36363f\nconst COLOR_FORK = 0xb8bcc4 // silver/light gray (레퍼런스)\nconst COLOR_TIRE = 0x171719\nconst COLOR_RIM = 0x707080\nconst COLOR_HUB = 0xb8b8c0\nconst COLOR_SEAT = 0x14141c\nconst COLOR_STEERING = 0x202028\nconst COLOR_GUARD = 0x252530\nconst COLOR_ROOF = 0xa8acb4 // 운전석 지붕 (실버)\nconst COLOR_HYDRAULIC = 0xc8ccd8\nconst COLOR_CHAIN = 0x4a4a55\nconst COLOR_WINDOW = 0x88aacc\nconst COLOR_TAIL = 0xff2626\nconst COLOR_HEADLIGHT = 0xfff7d4\n\nexport class Forklift3D extends RealObjectGroup {\n /**\n * Inner group that holds the actual mesh tree. Rotated π around Y so\n * the procedural model (drawn with forks pointing along component-local\n * +Z) aligns with things-scene's vehicle convention of -Z forward.\n *\n * Carriers attach onto this group (not `object3d`) so they inherit the\n * same rotation as the visible mesh — `cargoMount` coordinates remain\n * authored in the model's natural +Z-forward frame and the wrapper\n * transforms them to match the visible forks.\n */\n private _modelGroup?: THREE.Group\n\n get modelGroup(): THREE.Group | undefined {\n return this._modelGroup\n }\n\n /** Local-frame (-Z forward) fork-tip top surface — where cargo sits. */\n get cargoMount(): { x: number; y: number; z: number; width: number; depth: number } {\n const { width, height, depth = 200 } = this.component.state\n const raw = (this.component.state.forkHeight as number) ?? 0\n const forkHeight = Math.max(0, Math.min(raw, depth * 0.85))\n const wheelR = depth * 0.07\n const forkH = depth * 0.018\n const forkLen = height * 0.42\n const y = -depth / 2 + wheelR + forkHeight + forkH\n const z = -(height * 0.42 + forkLen / 2) // forks point -Z\n return { x: 0, y, z, width: width * 0.4, depth: forkLen }\n }\n\n build() {\n super.build()\n\n // ── State + clamping ─────────────────────────────────────────────\n const { width, height } = this.component.state\n // Resolve depth via the NaN-safe getter so a freshly-created Forklift\n // (template doesn't carry `depth`; Placeable.added writes it via setState\n // which races with the first build) renders with the Placeable archetype\n // default instead of a hard-coded fallback. The hard-coded value was\n // visually wrong-sized on the first frame and only \"snapped\" to a normal\n // shape after a 3D mode re-entry triggered a fresh build.\n const depth = this.effectiveDepth\n const bodyColor = (this.component.state.bodyColor as string) || '#ffc107'\n const lampEmissive = (this.component.state.lampEmissive as string) || '#333333'\n const status = this.component.state.status\n const lampIntensity = status && status !== 'idle' ? 1.5 : 0.2\n const forkHeightRaw = (this.component.state.forkHeight as number) ?? 0\n const forkHeight = Math.max(0, Math.min(forkHeightRaw, depth * 0.85))\n\n // ── Proportions (볼륨감 강화) ─────────────────────────────────────\n const baseY = -depth / 2\n const wheelR = depth * 0.14 // 더 큰 휠로 무거운 산업차량 느낌\n const chassisH = depth * 0.38 // 더 두툼한 본체\n const cabH = depth * 0.22\n const guardH = depth * 0.28\n const cwH = depth * 0.62 // counterweight 더 높이 키워 후방 매스감 확보\n const cwD = height * 0.28 // counterweight 더 깊게\n const chassisLen = height * 0.62 // 본체 길이 키움\n const chassisExtrudeW = width * 0.88 // 본체 폭 키움 (이전 0.78)\n const cabFloorY = baseY + wheelR + chassisH * 0.85\n\n // ── Materials (매트한 painted look — 레퍼런스 일관성) ────────────\n const bodyMat = new THREE.MeshStandardMaterial({\n color: bodyColor,\n metalness: 0.0,\n roughness: 0.65\n })\n const bodyShadeMat = new THREE.MeshStandardMaterial({\n color: new THREE.Color(bodyColor).multiplyScalar(0.72),\n metalness: 0.0,\n roughness: 0.65\n })\n // counterweight — 본체와 같은 색 (레퍼런스: 통합된 한 덩어리 느낌).\n const cwMat = bodyMat\n const mastMat = new THREE.MeshStandardMaterial({\n color: COLOR_MAST,\n metalness: 0.10,\n roughness: 0.65\n })\n const forkMat = new THREE.MeshStandardMaterial({\n color: COLOR_FORK,\n metalness: 0.20,\n roughness: 0.55\n })\n const tireMat = new THREE.MeshStandardMaterial({ color: COLOR_TIRE, roughness: 0.95 })\n const rimMat = new THREE.MeshStandardMaterial({ color: COLOR_RIM, metalness: 0.80, roughness: 0.30 })\n const hubMat = new THREE.MeshStandardMaterial({ color: COLOR_HUB, metalness: 0.85, roughness: 0.25 })\n const seatMat = new THREE.MeshStandardMaterial({ color: COLOR_SEAT, roughness: 0.85 })\n const guardMat = new THREE.MeshStandardMaterial({ color: COLOR_GUARD, metalness: 0.75, roughness: 0.40 })\n const hydraulicMat = new THREE.MeshStandardMaterial({ color: COLOR_HYDRAULIC, metalness: 0.95, roughness: 0.10 })\n const chainMat = new THREE.MeshStandardMaterial({ color: COLOR_CHAIN, metalness: 0.80, roughness: 0.40 })\n const windowMat = new THREE.MeshStandardMaterial({\n color: COLOR_WINDOW, metalness: 0.20, roughness: 0.05,\n transparent: true, opacity: 0.55\n })\n const tailMat = new THREE.MeshStandardMaterial({\n color: COLOR_TAIL, emissive: COLOR_TAIL, emissiveIntensity: 0.6,\n metalness: 0.10, roughness: 0.40\n })\n const headlightMat = new THREE.MeshStandardMaterial({\n color: COLOR_HEADLIGHT, emissive: COLOR_HEADLIGHT, emissiveIntensity: 0.4,\n metalness: 0.10, roughness: 0.30\n })\n\n // ────────────────────────────────────────────────────────────────\n // 1. CHASSIS BODY — sculpted side profile + width via ExtrudeGeometry\n // ────────────────────────────────────────────────────────────────\n const chassisGroup = new THREE.Group()\n chassisGroup.position.set(0, baseY + wheelR, 0) // wheels rest on floor\n\n // Side profile (looking from +X, **-Z forward**, +Y up).\n // sideShape's first axis is the vehicle length axis (+X = front, -X = back).\n // `rotateY(+π/2)` maps sideShape's +X to world -Z (= forward), giving the\n // -Z-forward convention. (Earlier the chassis used the same +π/2 mapping,\n // i.e. it was already -Z-forward; the rest of the model used z-direct\n // positions in the OPPOSITE sign convention. Aligning the rest to -Z\n // forward — by sign-flipping the direct z coords elsewhere — left the\n // chassis untouched as the canonical -Z-forward part.)\n const zFront = chassisLen * 0.5\n const zBack = -chassisLen * 0.5\n const hoodH = chassisH * 0.55\n const stepZ = chassisLen * 0.10\n const seatH = chassisH * 0.85\n\n const sideShape = new THREE.Shape()\n sideShape.moveTo(zFront, 0)\n sideShape.lineTo(zFront, hoodH) // up to hood top\n sideShape.lineTo(stepZ * 1.2, hoodH) // forward hood flat\n sideShape.lineTo(stepZ * 0.4, seatH) // sloped step up to seat platform\n sideShape.lineTo(zBack + stepZ, seatH) // platform flat to rear\n sideShape.lineTo(zBack, seatH * 1.05) // tiny lip into counterweight\n sideShape.lineTo(zBack, 0) // down to ground\n sideShape.lineTo(zFront, 0)\n\n const chassisGeo = new THREE.ExtrudeGeometry(sideShape, {\n depth: chassisExtrudeW,\n bevelEnabled: true,\n bevelSegments: 2,\n bevelSize: chassisH * 0.04,\n bevelThickness: chassisH * 0.04,\n curveSegments: 6\n })\n // rotateY(+π/2): sideShape +X (front) → world -Z (forward).\n // After rotateY(+π/2), extrude depth (sideShape +Z) → world +X.\n // depth range [0, extrudeW] → world X range [0, extrudeW]. Centred via\n // translate(-extrudeW/2). Wait — that's wrong for [0, extrudeW]; let\n // me recompute explicitly:\n // rotateY(+π/2): (x,y,z) → (z, y, -x)\n // ExtrudeGeometry produces verts with z in [0, depth]; after rotation\n // their X component = original Z, so X range [0, depth]. Translating\n // X by -depth/2 centres at 0. ✓\n chassisGeo.rotateY(Math.PI / 2)\n chassisGeo.translate(-chassisExtrudeW / 2, 0, 0)\n const chassisMesh = new THREE.Mesh(chassisGeo, bodyMat)\n chassisMesh.castShadow = true\n chassisMesh.receiveShadow = true\n chassisGroup.add(chassisMesh)\n\n this.object3d.add(chassisGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 2. COUNTERWEIGHT — sculpted rear mass (tapered, distinct from chassis)\n // ────────────────────────────────────────────────────────────────\n const cwGroup = new THREE.Group()\n // counterweight in world: back of vehicle = +Z (since -Z is forward).\n const cwZ = -zBack + cwD * 0.5\n\n // Base — wide, rectangular with rounded corners, sits low\n const cwBaseGeo = new RoundedBoxGeometry(width * 0.96, cwH * 0.70, cwD, 3, cwH * 0.05)\n const cwBaseMesh = new THREE.Mesh(cwBaseGeo, cwMat)\n cwBaseMesh.position.set(0, baseY + wheelR + cwH * 0.35, cwZ)\n cwBaseMesh.castShadow = true\n cwGroup.add(cwBaseMesh)\n\n // Top — narrower, slightly forward — gives the chamfered cast-iron look\n const cwTopGeo = new RoundedBoxGeometry(width * 0.82, cwH * 0.32, cwD * 0.85, 3, cwH * 0.04)\n const cwTopMat = new THREE.MeshStandardMaterial({\n color: new THREE.Color(bodyColor).multiplyScalar(0.65),\n metalness: 0.30, roughness: 0.55\n })\n const cwTopMesh = new THREE.Mesh(cwTopGeo, cwTopMat)\n cwTopMesh.position.set(0, baseY + wheelR + cwH * 0.70 + cwH * 0.16, cwZ + cwD * 0.05)\n cwTopMesh.castShadow = true\n cwGroup.add(cwTopMesh)\n\n this.object3d.add(cwGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 3. CAB — open frame: pillars + roof + seat + steering\n // ────────────────────────────────────────────────────────────────\n const cabGroup = new THREE.Group()\n const cabRoofY = cabFloorY + cabH\n const pillarT = width * 0.025\n const pillarPositions: [number, number][] = [\n [width * 0.27, -height * 0.05], // front-right (front = -Z)\n [width * 0.27, height * 0.28], // rear-right (rear = +Z)\n [-width * 0.27, -height * 0.05],\n [-width * 0.27, height * 0.28]\n ]\n\n const pillarGeos: THREE.BufferGeometry[] = []\n for (const [x, z] of pillarPositions) {\n const g = new RoundedBoxGeometry(pillarT, cabH, pillarT, 1, pillarT * 0.2)\n g.translate(x, cabFloorY + cabH / 2, z)\n pillarGeos.push(g)\n }\n const pillarsMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(pillarGeos), bodyShadeMat)\n pillarsMesh.castShadow = true\n cabGroup.add(pillarsMesh)\n\n // Operator seat (간단히 좌석 + 등받이만)\n const seatGeo = new RoundedBoxGeometry(width * 0.28, cabH * 0.40, height * 0.20, 2, width * 0.03)\n const seatMesh = new THREE.Mesh(seatGeo, seatMat)\n seatMesh.position.set(0, cabFloorY + cabH * 0.22, height * 0.18) // seat at rear of cab\n cabGroup.add(seatMesh)\n\n const backGeo = new RoundedBoxGeometry(width * 0.28, cabH * 0.65, height * 0.04, 2, width * 0.02)\n const backMesh = new THREE.Mesh(backGeo, seatMat)\n backMesh.position.set(0, cabFloorY + cabH * 0.55, height * 0.27) // backrest behind seat\n cabGroup.add(backMesh)\n\n // Steering wheel — 운전석 앞에 작은 검정 링 (식별성).\n const steeringMat = new THREE.MeshStandardMaterial({\n color: COLOR_STEERING, metalness: 0.4, roughness: 0.55\n })\n const colGeo = new THREE.CylinderGeometry(width * 0.014, width * 0.020, cabH * 0.45, 12)\n colGeo.rotateX(-Math.PI * 0.12)\n const colMesh = new THREE.Mesh(colGeo, steeringMat)\n colMesh.position.set(0, cabFloorY + cabH * 0.27, height * 0.05) // forward of seat (toward forks = -Z, but column is in front of seat which is at +0.18)\n cabGroup.add(colMesh)\n const swGeo = new THREE.TorusGeometry(width * 0.10, width * 0.013, 6, 18)\n swGeo.rotateX(Math.PI / 2 - Math.PI * 0.12)\n const swMesh = new THREE.Mesh(swGeo, steeringMat)\n swMesh.position.set(0, cabFloorY + cabH * 0.50, -height * 0.01) // wheel slightly forward of column\n cabGroup.add(swMesh)\n\n this.object3d.add(cabGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 4. OVERHEAD GUARD — ROPS structure above cab\n // ────────────────────────────────────────────────────────────────\n const guardGroup = new THREE.Group()\n const guardPostT = width * 0.024\n const guardX = width * 0.27\n const guardZF = -height * 0.05 // front of guard at -Z\n const guardZB = height * 0.38 // rear of guard at +Z\n const guardPostY = cabRoofY + guardH / 2\n\n const guardGeos: THREE.BufferGeometry[] = []\n for (const xSign of [-1, 1]) {\n for (const z of [guardZF, guardZB]) {\n const g = new THREE.BoxGeometry(guardPostT, guardH, guardPostT)\n g.translate(xSign * guardX, guardPostY, z)\n guardGeos.push(g)\n }\n }\n // Roof grid (3 lateral + 3 longitudinal bars)\n const roofY = guardPostY + guardH / 2 + guardPostT / 2\n // Span is positive (guardZB is rear/+Z, guardZF is front/-Z, rear − front).\n const roofZSpan = guardZB - guardZF\n for (const xFrac of [-1, 0, 1]) {\n const g = new THREE.BoxGeometry(guardPostT * 0.7, guardPostT * 0.7, roofZSpan + guardPostT)\n g.translate(xFrac * guardX, roofY, (guardZF + guardZB) / 2)\n guardGeos.push(g)\n }\n for (const zFrac of [-1, 0, 1]) {\n const g = new THREE.BoxGeometry(2 * guardX + guardPostT, guardPostT * 0.7, guardPostT * 0.7)\n g.translate(0, roofY, (guardZF + guardZB) / 2 + zFrac * roofZSpan * 0.5)\n guardGeos.push(g)\n }\n const guardMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(guardGeos), guardMat)\n guardMesh.castShadow = true\n guardGroup.add(guardMesh)\n\n // Roof panel — 솔리드 그레이 (레퍼런스 일관성).\n const roofPanelMat = new THREE.MeshStandardMaterial({\n color: COLOR_ROOF, metalness: 0.25, roughness: 0.55\n })\n const roofPanelW = 2 * guardX + guardPostT * 1.2\n const roofPanelD = guardZB - guardZF + guardPostT * 1.2\n const roofPanelGeo = new RoundedBoxGeometry(roofPanelW, depth * 0.025, roofPanelD, 2, depth * 0.012)\n const roofPanelMesh = new THREE.Mesh(roofPanelGeo, roofPanelMat)\n roofPanelMesh.position.set(0, roofY + depth * 0.012, (guardZF + guardZB) / 2)\n roofPanelMesh.castShadow = true\n guardGroup.add(roofPanelMesh)\n\n this.object3d.add(guardGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 5. MAST ASSEMBLY — rails + crossbar + hydraulic + chains + carriage + forks\n // ────────────────────────────────────────────────────────────────\n const mastGroup = new THREE.Group()\n const mastH = depth * 0.95\n const mastRailW = width * 0.06\n const mastRailD = height * 0.03\n const mastSpacing = width * 0.45\n // chassis front is now at -Z (forward); mast attaches just ahead.\n const mastZ = -(chassisLen / 2 + mastRailD)\n const mastY = baseY + wheelR + mastH / 2\n\n // Two main rails (rounded for visual softness)\n for (const xSign of [-1, 1]) {\n const railGeo = new RoundedBoxGeometry(mastRailW, mastH, mastRailD, 2, mastRailW * 0.20)\n const railMesh = new THREE.Mesh(railGeo, mastMat)\n railMesh.position.set((xSign * mastSpacing) / 2, mastY, mastZ)\n railMesh.castShadow = true\n mastGroup.add(railMesh)\n }\n\n // Crossbar at top\n const crossbarGeo = new RoundedBoxGeometry(\n mastSpacing + mastRailW, mastRailD * 1.3, mastRailD * 1.1, 2, mastRailW * 0.15\n )\n const crossbarMesh = new THREE.Mesh(crossbarGeo, mastMat)\n crossbarMesh.position.set(0, baseY + wheelR + mastH, mastZ)\n crossbarMesh.castShadow = true\n mastGroup.add(crossbarMesh)\n\n // Hydraulic cylinder (center, between rails)\n const hydCylR = mastRailW * 0.42\n const hydCylH = mastH * 0.78\n const hydCylGeo = new THREE.CylinderGeometry(hydCylR, hydCylR * 1.05, hydCylH, 20)\n const hydCylMesh = new THREE.Mesh(hydCylGeo, hydraulicMat)\n hydCylMesh.position.set(0, baseY + wheelR + hydCylH / 2 + mastRailD * 0.5, mastZ + mastRailD * 0.15) // hydraulic behind mast (+Z = back)\n hydCylMesh.castShadow = true\n mastGroup.add(hydCylMesh)\n\n // Piston rod (length tracks forkHeight)\n const pistonR = hydCylR * 0.55\n const pistonH = hydCylH * 0.45 + forkHeight * 0.7\n const pistonGeo = new THREE.CylinderGeometry(pistonR, pistonR, pistonH, 16)\n const pistonMesh = new THREE.Mesh(pistonGeo, hydraulicMat)\n pistonMesh.position.set(\n 0,\n baseY + wheelR + hydCylH + pistonH / 2 + mastRailD * 0.5,\n mastZ + mastRailD * 0.15 // piston behind mast (+Z)\n )\n mastGroup.add(pistonMesh)\n\n // Carriage (sliding plate) + load backrest grid\n const carriageY = baseY + wheelR + forkHeight + cwH * 0.05\n const carriageW = mastSpacing + mastRailW\n const carriageH = chassisH * 0.40\n const carriageD = mastRailD * 0.7\n const carriageGeo = new RoundedBoxGeometry(carriageW, carriageH, carriageD, 2, carriageH * 0.10)\n const carriageMesh = new THREE.Mesh(carriageGeo, forkMat)\n carriageMesh.position.set(0, carriageY + carriageH / 2, mastZ - mastRailD) // carriage forward of mast (-Z)\n carriageMesh.castShadow = true\n mastGroup.add(carriageMesh)\n\n // Load backrest — carriage 위로 수직 슬랫 그리드 (하중 받침 케이지).\n // 레퍼런스의 distinctive feature: 적재물이 운전자 쪽으로 넘어오지 않게 막는 격자.\n const backrestH = carriageH * 1.6\n const backrestY = carriageY + carriageH + backrestH / 2\n const backrestZ = mastZ - mastRailD // backrest forward of mast (-Z)\n const slatT = mastRailD * 0.5\n const slatGeos: THREE.BufferGeometry[] = []\n // 5 vertical slats\n for (let i = 0; i < 5; i++) {\n const t = i / 4\n const slatX = -carriageW / 2 + carriageH * 0.15 + t * (carriageW - carriageH * 0.30)\n const sg = new THREE.BoxGeometry(slatT, backrestH, slatT)\n sg.translate(slatX, backrestY, backrestZ)\n slatGeos.push(sg)\n }\n // Top + bottom rails connecting the slats\n for (const ySign of [-1, 1]) {\n const rg = new THREE.BoxGeometry(carriageW * 0.92, slatT, slatT)\n rg.translate(0, backrestY + ySign * (backrestH / 2 - slatT / 2), backrestZ)\n slatGeos.push(rg)\n }\n const backrestMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(slatGeos), forkMat)\n backrestMesh.castShadow = true\n mastGroup.add(backrestMesh)\n\n // Forks (L-shape via ExtrudeGeometry — heel + horizontal blade)\n const forkLen = height * 0.42\n const forkW = width * 0.10\n const forkH = depth * 0.018\n const forkBladeY = carriageY + forkH / 2\n for (const xSign of [-1, 1]) {\n const heelH = carriageH * 0.85\n const fs = new THREE.Shape()\n fs.moveTo(0, 0)\n fs.lineTo(forkLen, 0)\n fs.lineTo(forkLen, forkH * 0.5)\n fs.lineTo(forkH, forkH * 1.0)\n fs.lineTo(forkH, heelH)\n fs.lineTo(0, heelH)\n fs.lineTo(0, 0)\n const forkGeo = new THREE.ExtrudeGeometry(fs, {\n depth: forkW,\n bevelEnabled: true,\n bevelSegments: 1,\n bevelSize: forkH * 0.18,\n bevelThickness: forkH * 0.18\n })\n // rotateY(+π/2): fork shape +X (blade tip) → world -Z (forward).\n forkGeo.rotateY(Math.PI / 2)\n // ExtrudeGeometry 의 depth 는 +Z 방향으로 자라고, rotateY(π/2) 후 +X 방향.\n // 즉 fork 의 local origin (translate 적용점) 은 fork 의 LEFT 모서리. fork 중심은\n // origin + forkW/2. 좌우 대칭으로 배치하려면 중심을 xSign * mastSpacing * 0.45\n // 에 두어야 하므로 translate.x = xSign * 0.45 - forkW/2. 기존엔 +forkW/2 라서\n // 양쪽 fork 가 동일 방향으로 forkW 만큼 쏠려있던 버그.\n forkGeo.translate(\n xSign * mastSpacing * 0.45 - forkW / 2,\n forkBladeY,\n mastZ - mastRailD - carriageD // heel forward of carriage (-Z)\n )\n const forkMesh = new THREE.Mesh(forkGeo, forkMat)\n forkMesh.castShadow = true\n mastGroup.add(forkMesh)\n }\n\n this.object3d.add(mastGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 6. WHEELS — tire + rim disc + spokes (drive front, caster rear)\n // ────────────────────────────────────────────────────────────────\n const wheelW = depth * 0.04\n const wheelGroup = new THREE.Group()\n\n const tireGeos: THREE.BufferGeometry[] = []\n const rimGeos: THREE.BufferGeometry[] = []\n const hubGeos: THREE.BufferGeometry[] = []\n\n // Front (drive) wheels — slightly larger. Front of vehicle is -Z.\n for (const xSign of [-1, 1]) {\n const cx = xSign * width * 0.42\n const cz = -height * 0.30\n const r = wheelR * 1.05\n\n const tire = new THREE.CylinderGeometry(r, r, wheelW, 24)\n tire.rotateZ(Math.PI / 2)\n tire.translate(cx, baseY + r, cz)\n tireGeos.push(tire)\n\n const rim = new THREE.CylinderGeometry(r * 0.55, r * 0.55, wheelW * 0.85, 18)\n rim.rotateZ(Math.PI / 2)\n rim.translate(cx + xSign * wheelW * 0.10, baseY + r, cz)\n rimGeos.push(rim)\n }\n\n // Rear (caster) wheels — smaller. Rear of vehicle is +Z.\n for (const xSign of [-1, 1]) {\n const cx = xSign * width * 0.36\n const cz = height * 0.32\n const r = wheelR * 0.78\n\n const tire = new THREE.CylinderGeometry(r, r, wheelW * 0.85, 20)\n tire.rotateZ(Math.PI / 2)\n tire.translate(cx, baseY + r, cz)\n tireGeos.push(tire)\n\n const rim = new THREE.CylinderGeometry(r * 0.55, r * 0.55, wheelW * 0.7, 16)\n rim.rotateZ(Math.PI / 2)\n rim.translate(cx + xSign * wheelW * 0.08, baseY + r, cz)\n rimGeos.push(rim)\n }\n\n const tireMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(tireGeos), tireMat)\n tireMesh.castShadow = true\n wheelGroup.add(tireMesh)\n\n const rimMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(rimGeos), rimMat)\n rimMesh.castShadow = true\n wheelGroup.add(rimMesh)\n\n if (hubGeos.length > 0) {\n const hubMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(hubGeos), hubMat)\n wheelGroup.add(hubMesh)\n }\n\n this.object3d.add(wheelGroup)\n\n // ────────────────────────────────────────────────────────────────\n // 7. STATUS LAMP — sculpted (base + body + dome) on guard top\n // ────────────────────────────────────────────────────────────────\n const lampGroup = new THREE.Group()\n const lampR = Math.min(width, height) * 0.04\n const lampH = lampR * 1.5\n const lampMat = new THREE.MeshStandardMaterial({\n color: lampEmissive, emissive: lampEmissive,\n emissiveIntensity: lampIntensity,\n metalness: 0.0, roughness: 0.30\n })\n\n // Base disc\n const lbGeo = new THREE.CylinderGeometry(lampR * 1.15, lampR * 1.15, lampR * 0.25, 16)\n const lbMesh = new THREE.Mesh(lbGeo, guardMat)\n lbMesh.position.set(0, roofY + guardPostT * 0.5 + lampR * 0.125, (guardZF + guardZB) / 2)\n lampGroup.add(lbMesh)\n\n // Body\n const lyGeo = new THREE.CylinderGeometry(lampR, lampR * 0.95, lampH, 16)\n const lyMesh = new THREE.Mesh(lyGeo, lampMat)\n lyMesh.position.set(0, roofY + guardPostT * 0.5 + lampR * 0.25 + lampH / 2, (guardZF + guardZB) / 2)\n lampGroup.add(lyMesh)\n\n // Dome\n const ldGeo = new THREE.SphereGeometry(lampR, 16, 8, 0, Math.PI * 2, 0, Math.PI / 2)\n const ldMesh = new THREE.Mesh(ldGeo, lampMat)\n ldMesh.position.set(0, roofY + guardPostT * 0.5 + lampR * 0.25 + lampH, (guardZF + guardZB) / 2)\n lampGroup.add(ldMesh)\n\n this.object3d.add(lampGroup)\n\n // NOTE: model is drawn with forks pointing along component-local +Z.\n // This is the natural authoring axis but doesn't match things-scene's\n // vehicle convention of -Z forward — meaning the visible heading is\n // 180° off the travel heading set by Waypoint.\n //\n // Earlier we wrapped all children in an inner Group rotated π to fix\n // this without rewriting geometry. That wrap collided with reparent:\n // every build() rebuilt the wrap from scratch, which dropped attached\n // carriers. Removed.\n //\n // Direction fix is deferred — proper resolution is rewriting the mesh\n // coordinates with forks along -Z (or applying yaw at the model level\n // in a way `clear()`/`build()` doesn't undo). Until then, the forklift\n // visually points opposite to its travel direction; reparent works\n // correctly though.\n }\n\n updateDimension() {}\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if (\n 'status' in after ||\n 'bodyColor' in after ||\n 'lampEmissive' in after ||\n 'forkHeight' in after ||\n 'width' in after ||\n 'height' in after ||\n 'depth' in after\n ) {\n this.update()\n return\n }\n super.onchange(after, before)\n }\n\n updateAlpha() {}\n}\n"]}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@operato/scene-transport",
3
3
  "description": "Transport-domain components for things-scene (smart factory / logistics) — forklift, worker, AGV.",
4
4
  "author": "heartyoh",
5
- "version": "10.0.0-beta.25",
5
+ "version": "10.0.0-beta.26",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "module": "dist/index.js",
@@ -45,5 +45,5 @@
45
45
  "typescript": "^5.0.4"
46
46
  },
47
47
  "prettier": "@hatiolab/prettier-config",
48
- "gitHead": "84100604ffa30c28a0153c99666e9bd60f23bafb"
48
+ "gitHead": "abfdc2f8fe36fe7ad24e56a07626722a1192a422"
49
49
  }
@@ -461,8 +461,13 @@ export class Forklift3D extends RealObjectGroup {
461
461
  })
462
462
  // rotateY(+π/2): fork shape +X (blade tip) → world -Z (forward).
463
463
  forkGeo.rotateY(Math.PI / 2)
464
+ // ExtrudeGeometry 의 depth 는 +Z 방향으로 자라고, rotateY(π/2) 후 +X 방향.
465
+ // 즉 fork 의 local origin (translate 적용점) 은 fork 의 LEFT 모서리. fork 중심은
466
+ // origin + forkW/2. 좌우 대칭으로 배치하려면 중심을 xSign * mastSpacing * 0.45
467
+ // 에 두어야 하므로 translate.x = xSign * 0.45 - forkW/2. 기존엔 +forkW/2 라서
468
+ // 양쪽 fork 가 동일 방향으로 forkW 만큼 쏠려있던 버그.
464
469
  forkGeo.translate(
465
- xSign * mastSpacing * 0.45 + forkW / 2,
470
+ xSign * mastSpacing * 0.45 - forkW / 2,
466
471
  forkBladeY,
467
472
  mastZ - mastRailD - carriageD // heel forward of carriage (-Z)
468
473
  )