Skip to content

Commit 47c2870

Browse files
committed
アバターがどの方向を向いていても腕の回転補正が動作するように修正
1 parent 286600f commit 47c2870

1 file changed

Lines changed: 69 additions & 14 deletions

File tree

Assets/Scripts/Avatar/WristRotationFix.cs

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,11 @@ public void SetVRIK(VRIK setIK)
123123
if (eventId != null) IKManager.Instance.RemoveOnPostUpdate(eventId.Value);
124124
ik = setIK;
125125

126-
LeftArmFixItem = new ArmFixItem(ik.references.leftShoulder, ik.references.leftUpperArm, ik.references.leftForearm, ik.references.leftHand);
127-
RightArmFixItem = new ArmFixItem(ik.references.rightShoulder, ik.references.rightUpperArm, ik.references.rightForearm, ik.references.rightHand);
126+
// 基準となるTransformを取得(胸が優先、なければルート)
127+
Transform referenceTransform = ik.references.chest ?? ik.references.root;
128+
129+
LeftArmFixItem = new ArmFixItem(ik.references.leftShoulder, ik.references.leftUpperArm, ik.references.leftForearm, ik.references.leftHand, referenceTransform);
130+
RightArmFixItem = new ArmFixItem(ik.references.rightShoulder, ik.references.rightUpperArm, ik.references.rightForearm, ik.references.rightHand, referenceTransform);
128131

129132
// 設定を再読み込み
130133
LoadSettingsValues();
@@ -148,8 +151,8 @@ private void ApplyArmTwistFix(ArmFixItem item)
148151
Quaternion currentForearmRotation = item.Forearm.rotation;
149152

150153
// 1. UpperArmとForearmの現在の回転からTwist成分のみを除去し、Swing成分のみを残す
151-
Quaternion upperArmSwingOnly = RemoveTwistFromRotation(currentUpperArmRotation, item.InitialUpperArmRotation, item.UpperArmTwistAxis);
152-
Quaternion forearmSwingOnly = RemoveTwistFromRotation(currentForearmRotation, item.InitialForearmRotation, item.ForearmTwistAxis);
154+
Quaternion upperArmSwingOnly = RemoveTwistFromRotation(currentUpperArmRotation, item.InitialUpperArmRotation, item.UpperArmTwistAxis, item);
155+
Quaternion forearmSwingOnly = RemoveTwistFromRotation(currentForearmRotation, item.InitialForearmRotation, item.ForearmTwistAxis, item);
153156

154157
// 2. Swing成分のみの回転を適用(IKの結果を保持)
155158
item.UpperArm.rotation = upperArmSwingOnly;
@@ -214,17 +217,45 @@ private void ApplyArmTwistFix(ArmFixItem item)
214217
}
215218

216219
// 回転からTwist成分を除去し、Swing成分のみを残す
217-
private Quaternion RemoveTwistFromRotation(Quaternion currentRotation, Quaternion initialRotation, Vector3 twistAxis)
220+
private Quaternion RemoveTwistFromRotation(Quaternion currentRotation, Quaternion initialRotation, Vector3 twistAxis, ArmFixItem item)
218221
{
219-
// 初期回転からの相対回転を取得
220-
Quaternion relativeRotation = currentRotation * Quaternion.Inverse(initialRotation);
222+
Quaternion relativeRotation;
221223

222-
// Swing-Twist分解でSwing成分のみを抽出
223-
Quaternion swing, twist;
224-
SwingTwistDecomposition(relativeRotation, twistAxis, out swing, out twist);
224+
// 基準Transform(胸またはルート)を取得
225+
Transform referenceTransform = ik.references.chest ?? ik.references.root;
225226

226-
// Swing成分のみを初期回転に適用
227-
return swing * initialRotation;
227+
if (referenceTransform != null)
228+
{
229+
// 基準Transformを使った相対回転計算
230+
Quaternion currentReferenceRotation = referenceTransform.rotation;
231+
232+
// 現在の腕の回転を基準Transformからの相対回転として計算
233+
Quaternion currentArmRelativeToReference = Quaternion.Inverse(currentReferenceRotation) * currentRotation;
234+
235+
// 初期状態との相対回転を計算(基準Transformの回転変化の影響を除去)
236+
Quaternion initialArmRelativeToReference = (initialRotation == item.InitialUpperArmRotation)
237+
? item.InitialUpperArmRelativeToReference
238+
: item.InitialForearmRelativeToReference;
239+
240+
relativeRotation = currentArmRelativeToReference * Quaternion.Inverse(initialArmRelativeToReference);
241+
242+
// Swing-Twist分解でSwing成分のみを抽出
243+
Quaternion swing, twist;
244+
SwingTwistDecomposition(relativeRotation, twistAxis, out swing, out twist);
245+
246+
// 結果を基準Transformを基準としたワールド座標に戻す
247+
return currentReferenceRotation * (swing * initialArmRelativeToReference);
248+
}
249+
else
250+
{
251+
// 基準Transformがない場合は従来の方法
252+
relativeRotation = currentRotation * Quaternion.Inverse(initialRotation);
253+
254+
Quaternion swing, twist;
255+
SwingTwistDecomposition(relativeRotation, twistAxis, out swing, out twist);
256+
257+
return swing * initialRotation;
258+
}
228259
}
229260

230261
// HandのTwist角度を計算(Swing-Twist分解を使用)
@@ -316,8 +347,15 @@ public class ArmFixItem
316347
// T-ポーズ時の初期回転を保存
317348
public Quaternion InitialUpperArmRotation;
318349
public Quaternion InitialForearmRotation;
350+
351+
// 基準Transform(胸またはルート)の初期回転を保存
352+
public Quaternion InitialReferenceRotation;
353+
354+
// 腕の初期回転を基準Transformからの相対回転として保存
355+
public Quaternion InitialUpperArmRelativeToReference;
356+
public Quaternion InitialForearmRelativeToReference;
319357

320-
public ArmFixItem(Transform shoulder, Transform upperArm, Transform forearm, Transform hand)
358+
public ArmFixItem(Transform shoulder, Transform upperArm, Transform forearm, Transform hand, Transform referenceTransform)
321359
{
322360
Shoulder = shoulder;
323361
UpperArm = upperArm;
@@ -336,9 +374,26 @@ public ArmFixItem(Transform shoulder, Transform upperArm, Transform forearm, Tra
336374
// 初期状態のHandの回転を保存
337375
NeutralHandRotation = Quaternion.Inverse(forearm.rotation) * hand.rotation;
338376

339-
// T-ポーズ時の初期回転を保存
377+
// T-ポーズ時の絶対回転を保存
340378
InitialUpperArmRotation = upperArm.rotation;
341379
InitialForearmRotation = forearm.rotation;
380+
381+
// 基準Transform(胸またはルート)の初期回転を保存
382+
if (referenceTransform != null)
383+
{
384+
InitialReferenceRotation = referenceTransform.rotation;
385+
386+
// 腕の回転を基準Transformからの相対回転として保存
387+
InitialUpperArmRelativeToReference = Quaternion.Inverse(referenceTransform.rotation) * upperArm.rotation;
388+
InitialForearmRelativeToReference = Quaternion.Inverse(referenceTransform.rotation) * forearm.rotation;
389+
}
390+
else
391+
{
392+
// 基準Transformがない場合は従来の方法を使用
393+
InitialReferenceRotation = Quaternion.identity;
394+
InitialUpperArmRelativeToReference = upperArm.rotation;
395+
InitialForearmRelativeToReference = forearm.rotation;
396+
}
342397
}
343398
}
344399
}

0 commit comments

Comments
 (0)