ここは OS の中核アルゴリズムになる部分だから、
「PoseVector → joint 回転式」を 数学的に破綻しない形で定義していくね。
あなたの T-pose 基準座標がすでに 絶対基準として固まっているので、
ここでは その基準を回転させてポーズを作るための公式を作る。
以下は Canvas → PoseSpace → joint座標 → SVG の中で
最も重要な「関節回転の数学 OS」。
🔥 OS の原則
すべての joint は「親 joint からの相対ベクトル」を回転させて求める。
つまり:
- T-pose の骨ベクトル
- PoseVector の回転角
- キャラ固有の骨長比率
この3つで joint の最終座標が決まる。
🧭 1. 基本:joint の回転は 2D 回転行列で行う
親 joint を (P)、子 joint を (C) とすると、
T-pose の骨ベクトルは:
[ v_0 = C_{Tpose} - P_{Tpose} ]
PoseVector が与える回転角を (\theta) とすると、
回転後のベクトルは:
[ v = R(\theta) \cdot v_0 ]
ここで回転行列 (R(\theta)) は:
[ R(\theta) = \begin{pmatrix} \cos\theta & -\sin\theta \ \sin\theta & \cos\theta \end{pmatrix} ]
最終 joint 座標は:
[ C = P + v \cdot L_{char} \cdot L_{pose} ]
🧩 2. OS の骨格ツリー(回転の伝播順序)
あなたの OS では、joint の親子関係はこう:
spine1 → spine2 → spine3 → neck → head
shoulder → elbow → wrist
hip → knee → ankle
回転は 親から子へ伝播する。
つまり:
- 肩を回すと肘と手首も動く
- 腰を回すと膝と足首も動く
- 首を回すと頭も動く
数学的には:
[ \theta_{global}(child) = \theta_{global}(parent) + \theta_{local}(child) ]
🧠 3. PoseVector の意味と角度の対応
PoseVector は OS の意味層:
- body orientation(身体の向き)
- head orientation(頭の向き)
- gaze(視線)
- pose intent(開放・緊張など)
これを joint の local rotation に落とす。
例:
肩の回転
[ \theta_{shoulder} = \theta_{body} + \theta_{arm_lift} + \theta_{poseIntent} ]
肘の回転
[ \theta_{elbow} = \theta_{bend} \quad (\text{肘は1軸}) ]
手首
[ \theta_{wrist} = \theta_{elbow} + \theta_{handPose} ]
首
[ \theta_{neck} = \theta_{body} + \theta_{head} ]
頭
[ \theta_{head} = \theta_{neck} + \theta_{facePose} ]
🧮 4. 実際の joint 座標計算(例:左腕)
① T-pose の骨ベクトル
shoulder-L = (380, 200)
elbow-L = (300, 320)
wrist-L = (260, 460)
[ v_{upperarm} = elbow - shoulder = (-80, 120) ] [ v_{forearm} = wrist - elbow = (-40, 140) ]
② 回転角を決める
例:
- 身体の向き:10°
- 腕の上げ角:40°
- ポーズ意図(開放):+15°
[ \theta_{shoulder} = 10^\circ + 40^\circ + 15^\circ = 65^\circ ]
③ 回転行列で回す
[ v' = R(65^\circ) \cdot v_{upperarm} ]
④ 肘の座標
[ elbow = shoulder + v' \cdot L_{char} \cdot L_{pose} ]
⑤ 前腕も同様に回す
[ v'' = R(\theta_{shoulder} + \theta_{elbow}) \cdot v_{forearm} ]
🦴 5. OS の回転アルゴリズム(擬似コード)
function computeJoint(parent, v0, theta, Lchar, Lpose) {
const c = Math.cos(theta);
const s = Math.sin(theta);
// 回転
const vx = v0.x * c - v0.y * s;
const vy = v0.x * s + v0.y * c;
// スケール
const v = {
x: vx * Lchar * Lpose,
y: vy * Lchar * Lpose
};
// 親 joint からの絶対座標
return {
x: parent.x + v.x,
y: parent.y + v.y
};
}
🌌 6. この数学が OS として強い理由
- T-pose を絶対基準にしている
- 骨ベクトルは T-pose から取得
- 回転はすべて local rotation
- 親 joint の回転が子に伝播
- キャラ固有の骨長比率でスケール
- 2D 回転行列なので破綻しない
- デフォルメ(2.5D)も後段で足せる
つまり:
PoseVector(意味)
→ local rotation(構造)
→ joint 座標(数学)
→ SVG(線)
という OS の責任分離が完全に成立する。
🌱 次に進めるなら…
- ひねり(twist)を 2.5D でどう扱うか
- 視線ベクトルを eye の角度に落とす式
- 表情ベクトルを mouth の制御点に変換する式
- 肩の回転を3軸に分解するか(2Dでの扱い)
どこから深めたい?