Editor path 3D berbasis three.js + React tempat truk kontainer low-poly dapat
ditempatkan, diberi tujuan, dan berjalan mengikuti lintasan (garis + kurva Bezier)
dengan artikulasi kingpin yang realistis — trailer menekuk pada sambungan fifth
wheel saat menikung, digerakkan oleh library simulasi vehicle-path2.
Prasyarat: Node.js ≥ 20.19 (atau ≥ 22.12).
npm install
npm run dev # buka http://localhost:5173Kontrol mouse: klik kiri = aksi editor (sesuai mode aktif) · drag kanan = orbit kamera · drag tengah = pan · scroll = zoom.
- Line (tab PATH): drag kiri di tanah untuk menggambar garis lintasan (min. 3 m).
- Curve: drag dari satu garis ke garis lain — kurva Bezier penghubung dihitung
otomatis (tangent mode
proportional-40/magic-55bisa diganti di panel). Kurva digambar putus-putus dengan warna yang sama seperti garis. - Drag: geser endpoint/badan garis, titik attachment kurva, truk, atau marker tujuan.
- Start (tab VEHICLE): klik garis (panjang ≥ 12.3 m) untuk menempatkan truk.
- End: pilih truk, lalu klik garis tujuan — hijau = terjangkau, merah "no path" = tidak tersambung.
- ▶ Play: truk berangkat dengan kecepatan konstan (slider Speed), trailer berartikulasi pada kingpin, berhenti tepat di marker. ↺ Reset mengembalikan.
Panel punya dua tema — Paper (light, default) dan Slate (dark) — diganti lewat
tombol ☀/☾ di kanan atas panel; pilihan tersimpan ke localStorage
(key 3d-truck-theme-v1).
Panel juga menyediakan: daftar line (rename/edit koordinat/hapus), daftar curve (edit offset/hapus), Copy Snapshot (JSON ke clipboard), Import Snapshot, statistik scene, dan section Display:
- Truck opacity (10–100%): menembus-pandangkan semua truk.
- Cargo per-truk (kartu VEHICLE, saat truk dipilih): pilih mode muatan (Empty / 40ft / 2×20ft / 20ft Depan / 20ft Belakang) dan warna tiap kontainer. Mode 2×20ft punya dua warna terpisah (depan & belakang). Tersimpan per-truk ke localStorage; scene lama tanpa data cargo tampil sebagai 40ft putih.
- Axle markers (ON/OFF): palang penanda posisi axle hasil hitungan library — selalu pekat, tidak ikut transparan. Penempatan benar bila: palang amber segaris poros roda depan, slate di tengah antara dua axle penggerak tractor (pusat fifth wheel), merah di poros roda tengah tri-axle trailer.
Scene tersimpan otomatis ke localStorage (key 3d-truck-scene-v1) dan pulih saat
halaman dimuat ulang.
Semua koordinat dalam meter (1 unit = 1 m). Library vehicle-path2 bekerja di 2D
(x, y); dunia three.js memetakannya ke (x, 0, z) dengan y ≡ z.
src/
├── ContainerTruck.js Aset truk low-poly (vanilla three.js, beku & teruji)
├── Container.js Aset kontainer low-poly mandiri (box 40ft/20ft + warna)
├── App.tsx State scene + PathEngine + loop animasi (RAF)
├── types.ts Tipe editor + konstanta truk (axle [3.6, 8.7] m)
├── ids.ts Generator ID berurut (line-N / curve-N / vehicle-N)
├── persistence.ts Autosave localStorage + import/export snapshot
└── components/
├── Canvas3D.tsx Scene three.js + seluruh interaksi editor (raycast tanah)
├── Panel.tsx Panel kontrol (mode, daftar, vehicle, display)
└── three/
├── SceneSetup.ts Renderer, kamera, lampu, ground, raycast helper
├── PathLayer.ts Visual garis/kurva/marker/preview di tanah
├── TruckLayer.ts Instance ContainerTruck per vehicle + opacity + marker axle
└── pose.js Pemetaan pose: 3 posisi axle 2D → posisi/yaw/hitchAngle
Bagaimana truk mengikuti path — setiap truk adalah vehicle 3 axle di library
(axleSpacings = [3.6, 8.7]: axle depan → kingpin → pusat bogie trailer). Tiap frame
PathEngine.moveVehicle menggeser ketiga axle sejauh speed × deltaTime di sepanjang
path (kecepatan konstan, tanpa modul akselerasi); dari posisinya, pose.js menghitung:
posisi = axle kingpin (origin aset memang di kingpin)
yaw = −heading_tractor
hitch = wrapToPi(heading_tractor − heading_trailer) → ContainerTruck.hitchAngle
import { ContainerTruck } from './ContainerTruck.js';
const truck = new ContainerTruck(); // opsional: { cabColor, boxColor }
scene.add(truck); // extends THREE.Group, 21 mesh
truck.hitchAngle = Math.PI / 6; // artikulasi kingpin, clamp ±90°
truck.dispose(); // lepas resource GPU (geometry roda dibagi antar instance)| Perintah | Fungsi |
|---|---|
npm run dev |
Dev server Vite |
npm run build |
Typecheck (tsc --noEmit) + build produksi |
npm run preview |
Serve hasil build |
npm run typecheck |
Pemeriksaan TypeScript saja |
npm run smoke |
18 asersi aset ContainerTruck termasuk cargo (Node murni, tanpa browser) |
npm run check:pose |
11 asersi pemetaan pose 2D→3D |
npm run check:container |
11 asersi aset Container (dims 40ft/20ft, warna, dispose) |
Desain & rencana implementasi tiap fase tersimpan di repo:
docs/superpowers/specs/— spec yang disetujui (aset truk, editor + follow-path, transparansi + marker axle)docs/superpowers/plans/— implementation plan per fase
Referensi visual aset: Screenshot 2026-06-10 133628.png (truk kontainer 4 arah).
- Simulasi gerak multi-axle:
vehicle-path2(pola pemakaian mengikuti demo resminya). - Dibangun dengan three.js, React 19, TypeScript, dan Vite.