iT邦幫忙

2026 iThome 鐵人賽

DAY 26
0
Vibe Coding

使用 Vibe Coding 開發一套 Tutting 模擬器吧!系列 第 26 篇

📐DAY 26 | 3D 骨架🦴的關節角度限制

  • 分享至 

  • xImage
  •  

在拖曳 IK 目標球時,很容易將雙手拉扯到非人類解剖結構的怪異角度。如果 3D 模擬器跳出的姿勢是真人舞者根本無法做到的,那它就失去了作為編舞輔助工具與模擬器的價值了。

今天 DAY 26,我們要專注於為 XBOT 標準骨架注入關節角度限制(Joint Angular Limits)與人體工學限制,確保模擬器的每一次幾何折疊,都符合真實舞者的身體能力!

為什麼需要「關節角度限制」?

關節角度限制(Joint Angle Limits)是用來防止3D人偶或骨架做出超越真人極限的異常扭曲之功能。

在實務編舞測試中,如果沒有限制關節,我們會遇到以下生硬且不自然的動態:

  • 肩關節暴跳:在拖曳手臂 IK 時,肩膀會突然向下拉扯或向上反轉 360度,看起來像脫臼。
  • 手肘向後折斷:真實手肘只能向前收合,無法向後彎曲。純幾何 IK 若沒有設定 Pole 球與阻尼,手肘會無情地產生反向幾何。
  • 軀幹過度扭轉:脊椎與腰部的扭轉在真人身上通常只有數十度的極限,但模擬器預設可以隨意像扭毛巾一樣扭轉。
    這些生硬的動態會破壞 Tutting 的幾何剛性美感,因此,我們必須嚴格定義身體各大關節的 Euler 角 min、max 限制。

https://ithelp.ithome.com.tw/upload/images/20260831/201442889LXcEqsSwK.png

全骨架🦴關節限制角度明細

為了讓模擬器全面契合人體工學,我們針對 XBOT 標準骨架設定了以下嚴格的關節旋轉極限(左右側同步生效):

關節類別 關節名稱與代號 旋轉軸 / 運動方向 限制角度範圍 備註說明
1. 上肢與手臂關節 肩關節 / 鎖骨 (Clavicle L/R) 前後屈伸 -30° ~ 45°
上下聳肩 -15° ~ 30°
肩肱關節 (Shoulder L/R) 前屈 / 後伸 (Pitch) -60° ~ 180° 3 軸旋轉
內收 / 外展 (Roll) -50° ~ 180°
手臂內旋 / 外旋 (Yaw) -90° ~ 90°
手肘關節 (Elbow L/R) 屈曲 / 伸直 (X 軸) 0° ~ 145° 單軸限制;極限伸直 0°,完全收合 145°,嚴禁反向折斷
手腕關節 (Wrist L/R) 掌屈 / 背伸 -80° ~ 70° 2 軸旋轉
尺偏 / 橈偏 -30° ~ 20°
2. 軀幹與脊椎關節 腰椎 / 胸椎 (Spine & Spine1) 前後俯仰 -15° ~ 30° 單節阻尼限制
左右側彎 -15° ~ 15°
水平扭轉 -15° ~ 15°
上胸椎 / 頸根 (Spine2) 前後俯仰 -20° ~ 30° 軀幹頂端
水平扭轉 -20° ~ 20°
脊椎整體累加限制 軀幹整體前傾 / 後仰 -45° ~ 90° Spine + Spine1 + Spine2 總和
軀幹整體水平總扭轉 -45° ~ 45° 防止扭毛巾現象
頸部 / 頭部 (Neck & Head) 低頭 / 抬頭 -40° ~ 50°
左右轉頭 -70° ~ 70°
3. 下肢關節 髖關節 (Hip L/R) 前屈 / 後伸 -30° ~ 120° 3 軸旋轉
內收 / 外展 -30° ~ 45°
大腿內旋 / 外旋 -40° ~ 40°
膝蓋關節 (Knee L/R) 屈曲 / 伸直 (X 軸) -140° ~ 0° 單軸限制;禁止膝蓋向前反折
腳踝關節 (Ankle L/R) 跖屈 / 背屈 -45° ~ 20°
4. 掌指微觀關節 大拇指 (Thumb1 ~ Thumb3) CMC 掌指基部 -30° ~ 60° 雙手共 30 節
MCP / IP 指節 0° ~ 80° 僅向掌心收合
四指 (Index/Middle/Ring/Pinky 1~3) MCP 掌指根部 -10° ~ 90°
PIP / DIP 中末指節 0° ~ 100° 單向向掌心彎曲,無側向甩動

實作重點:關節限制架構與核心管道設計

1. 資料結構與持久化設計

針對系統中每個關節(ALL_JOINT_KEYS),獨立定義 X/Y/Z 三軸設定:

// 每個關節的三軸設定結構
{
  x: { enabled: true, min: 0, max: 145 },
  y: { enabled: false, min: -180, max: 180 },
  z: { enabled: false, min: -180, max: 180 }
}

2. 核心夾緊函式(Pure Functions)

3D Tuttinhg 模擬器中確保骨架角度符合人體工學限制(Joint Limits)的核心夾緊演算法(Pure Functions),主要功用是用來強制過濾並修剪不合法的角度,防止虛擬角色做出脫臼、反折或穿模等怪異動作。

// 單軸夾緊邏輯:含防呆與防修改保護
function clampAxis(val, config) {
  if (!config || !config.enabled) return val;
  const min = Math.min(config.min, config.max); // 防錯:使用者填反自動校正
  const max = Math.max(config.min, config.max);
  return THREE.MathUtils.clamp(val, min, max);
}

// 關節層級夾緊 (回傳全新陣列)
function clampJointAngles(jointKey, [x, y, z]) {
  const cfg = jointLimitsConfig[jointKey];
  if (!cfg) return [x, y, z];
  return [
    clampAxis(x, cfg.x),
    clampAxis(y, cfg.y),
    clampAxis(z, cfg.z)
  ];
}

3. 即時拖曳手感

使用者用滑鼠/ Gizmo 拖曳關節時,系統實時擷取旋轉並夾緊,直接將夾緊後的角度寫回骨骼 Quaternion。骨骼在拖曳當下即「頂住」邊界,避免放開滑鼠才彈回的突兀視覺。

4. UI 控制面板

  • 部位分組與搜尋:依據「軀幹、頭、手臂、腿、手指」分組收合,並提供即時名稱過濾搜尋框。
  • 簡潔互動:僅有勾選「啟用」後,才會展開該軸的數字輸入框。支援「全部展開」、「全部收合」與「恢復預設」批次功能。

https://ithelp.ithome.com.tw/upload/images/20260904/201442884ufmq51Mwo.png

結語

解決了骨架的「自然與限制」後,我們正式邁向了科技與人性的融合。3D 模擬器不僅要算得精準,更要算得自然。透過為 XBOT 注入完整的人體工學關節限制,我們確保了模擬器吐出的每一次「90 度手盒(Hand Box)」或「Threading 穿線招式」,都是舞者真正能上台演繹的動作。


關節角度限制(Joint Limits)功能規格Prompt

# 關節角度限制(Joint Limits)功能規格

請在一個使用骨骼(bone)+ 歐拉角驅動姿勢的 3D 角色系統中,新增「關節角度限制」功能,需求如下:

## 1. 資料結構

- 針對系統中每一個關節(`ALL_JOINT_KEYS`),各自建立 X/Y/Z 三軸獨立的限制設定:

  ``
  { enabled: boolean, min: number, max: number }
  ``

- 角度單位為度,數值定義為「相對 rest pose」的旋轉角,需與現有的 `target`/`current` 姿勢陣列使用同一套座標系。
- 每軸可獨立開關;未啟用時該軸完全不受影響,維持原本自由旋轉行為。
- 預設全部關節、全部軸皆為停用狀態(`enabled:false`),min/max 給合理預設值(例如 -180~180)。
- 設定需持久化到 `localStorage`,頁面重新載入時自動還原。

## 2. 核心夾緊函式

- 實作單軸夾緊函式:
  - 若未啟用則直接放行。
  - 若 min > max 則自動互換,避免使用者填反導致角度被鎖死在單一值。
  - 否則用 `clamp(v, min, max)`。
- 實作關節層級的夾緊函式:對輸入的 `[x, y, z]` 角度陣列,逐軸呼叫單軸夾緊函式,回傳新陣列(不可修改原始輸入)。
- 若某關節沒有對應的限制設定,原樣放行,不影響既有行為。

## 3. 生效範圍(所有角度寫入路徑都必須經過夾緊)

### 統一寫入入口
系統中所有「賦值姿勢角度」的地方(套用姿勢庫、匯入 JSON、關鍵影格編輯等)都必須經過同一個函式,寫入前先執行關節夾緊。

### 即時拖曳
使用者用滑鼠/觸控拖曳關節時,從骨骼目前旋轉反推出角度後,若超出限制:
- 資料層的角度要夾緊。
- 同時要把夾緊後的角度重新寫回骨骼本身的旋轉(quaternion),讓骨骼在拖曳過程中「即時頂住」邊界,而不是放開滑鼠才彈回去,確保操作手感一致、不違和。

### 設定變更即時生效
使用者在限制設定介面勾選啟用或修改 min/max 時,要立刻對該關節「目前」的姿勢角度重新夾緊一次;如果目前姿勢已超出新設定範圍,要馬上收回到範圍內,不必等待下一次操作。

## 4. UI 需求

- 依部位分組(例如:軀幹、頭、手臂、腿、手指)顯示所有關節的限制設定,各分組可個別收合。
- 提供關節名稱搜尋/過濾功能。
- 每個關節、每一軸顯示:一個「啟用」勾選框 + min/max 兩個數字輸入框;未啟用時輸入框應隱藏收起,保持畫面簡潔。
- 提供「全部展開」「全部收合」「恢復預設(全部停用)」等批次操作按鈕。
- 建議在介面上提示使用者:先不啟用限制、手動轉動關節觀察目前角度範圍,再回頭設定合理的 min/max 並啟用,避免亂填數值。


上一篇
📐DAY 25 | Tutting 最高階的技巧:想像力模擬
下一篇
📐DAY 27 | 讓虛擬接近物理現實:Tutting 模擬器的關節限制與碰撞偵測
系列文
使用 Vibe Coding 開發一套 Tutting 模擬器吧! 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言