深夜裡戴著耳機,放著自己最愛的 音樂,我正沉浸在 3D Tutting 模擬器的測試與編舞中。
但當我自己連續編了三組姿勢後,我突然發現了一個很致命的問題!
每當我想調整 Xbot 的手腕角度時,我的眼睛必須先離開 3D 角色,移動到左下角的 UI 面板,在一堆滑桿中找到相對應位置的滑桿,再把視線轉回 3D 角色確認角度……
這種眼神在 2D 面板與 3D 畫面之間頻繁切換,把舞者最寶貴的「直覺靈感」全都磨光了!
這時後思索,有什麼方法可以直覺地的進行編修呢?透過以下的對話過程,我與 AI 一步一步尋找答案。

我跟 AI 說:「舞者的視線應該 100% 停留在 3D 角色身上!能不能把控制面板直接『搬進 3D 空間裡』?」
我們決定引入 3D 視覺化 Helper(控制環 / TransformControls)!
現在,當我點擊 Xbot 的右肩膀或手肘時,關節周圍會直接亮起紅、綠、藍三色的 3D 旋轉弧線環。
我不需要去下方的面板找滑桿,直接用滑鼠點擊關節上的弧線、輕輕一拉,骨骼就直接順著該軸線轉動起來!
這讓操控感從原本的「在控制台打字設定」,瞬間變成了「手直接在 3D 空間裡撫摸、雕塑模型」的觸覺直覺!

但光能直接轉還不夠! Tutting 舞者是有「角度潔癖」的!
如果純靠手感轉動,你很容易轉出 89.3° 或 91.1° 這種尷尬的角度,為了微調那 0.7 度,眼神又得湊近看數值,心流再次被打斷。
於是我們加上了最靈魂的功能——角度貼合(Angle Snapping)!
我們設定了常用的切換步階(例如以 15° 或 45° 為一檔)。當我轉動 Helper 控制環時,只要接近 45°、90° 或 180°,程式就會瞬間觸發磁吸,角度自動精準吸附卡進 90 度直角!

加入3D Helper 後,我戴著耳機,滑鼠在 3D 舞台上直接點擊手肘連動 Helper,滑鼠甩過去——「喀噠!」卡進 90 度直角;點擊手腕 Helper 滑鼠一翻——「喀噠!」自動吸附 180 度貼平前臂!
一組原本要調 5 分鐘的複雜 Tutting 姿勢,現在 10 秒鐘就能在指尖順暢完成。
謝謝觀看~~
明天見!!
## 3D 關節控制環(核心需求,取代 2D 滑桿面板)
- 每根可控骨骼的世界座標位置放一顆小關節球(marker),每幀跟著骨骼移動,用 `MeshBasicMaterial` + `depthTest:false` 確保容易被點到、不被模型擋住
- 用 `Raycaster` 偵測滑鼠點擊(`pointerdown`→`pointerup`,中間移動距離小於一個閾值才算「點擊」而不是「拖曳視角」),點中關節球就用 `TransformControls`(`setMode("rotate")`)`attach()` 到該骨骼上,關節球要變色/放大表示已選取
- `TransformControls` 直接掛在被選中的骨骼(`Bone` 本身是 `Object3D`,可以直接 attach),拖曳環即時旋轉該骨骼
- 拖曳中:
- 監聽 `dragging-changed` 事件,拖曳時關閉 `OrbitControls`(避免相機跟著轉),並把該關節從每幀的 lerp 更新中排除,把控制權完全交給 `TransformControls`
- 監聽 `objectChange` 事件,即時把骨骼目前的 `quaternion` 反推回「相對 rest pose 的角度」(`deltaQuat = restQuat⁻¹ * bone.quaternion`,再轉成 Euler XYZ 角度),寫回姿勢資料,這樣鬆手後資料與視覺完全同步、不會跳動
- 提供「座標:本地/世界」按鈕,可切換 `TransformControls.setSpace()` 在 `local` 與 `world` 之間切換
- 提供選取狀態列:顯示目前選取的關節名稱、目前 X/Y/Z 角度(唯讀數值即時更新)、「取消選取」按鈕(`detach()`)、「此關節歸零」按鈕
- **不要**額外做 2D 滑桿或關節清單面板來控制角度——關節選取只透過點擊 3D 場景裡的關節球
## 角度貼合(Angle Snapping)
- 選取狀態列加一個下拉選單:關閉 / 15° / 30° / 45° / 90°
- 用 `TransformControls.setRotationSnap(THREE.MathUtils.degToRad(角度))` 實作,選「關閉」時傳 `null`
- 預設開啟 15°,拖曳旋轉環時會自動吸附到選定角度的倍數,符合 tutting 強調直角/幾何角度的視覺特徵