ここは 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での扱い)

どこから深めたい?