• R/O
  • SSH
  • HTTPS

mmdx: Commit


Commit MetaInfo

Revision922 (tree)
Time2012-01-10 00:54:46
Authorwilfrem

Log Message

TrueMyHeartのバグ修正。そのためにIIKLimitterインターフェイスを修正し、回転軸制限の機能を追加

Change Summary

Incremental Difference

--- trunk/MikuMikuDanceCore/Misc/DefaltIKLimitter.cs (revision 921)
+++ trunk/MikuMikuDanceCore/Misc/DefaltIKLimitter.cs (revision 922)
@@ -96,6 +96,42 @@
9696 }
9797 }
9898 /// <summary>
99+ /// IK計算時の回転軸制限クラス
100+ /// </summary>
101+ public class RotationAxisLimit
102+ {
103+ /// <summary>
104+ /// 回転制限を行う軸(X,Y,Z)
105+ /// </summary>
106+ public bool[] Limits { get; private set; }
107+ /// <summary>
108+ /// 既定のコンストラクタ
109+ /// </summary>
110+ public RotationAxisLimit()
111+ {
112+ Limits = new bool[3] { false, false, false };
113+ }
114+ /// <summary>
115+ /// 回転軸制限の適用
116+ /// </summary>
117+ /// <param name="rotationAxis"></param>
118+ public void Adjust(ref Vector3 rotationAxis)
119+ {
120+ if (Limits[0])
121+ {
122+ rotationAxis.X = 0;
123+ }
124+ if (Limits[1])
125+ {
126+ rotationAxis.Y = 0;
127+ }
128+ if (Limits[2])
129+ {
130+ rotationAxis.Z = 0;
131+ }
132+ }
133+ }
134+ /// <summary>
99135 /// 標準IKLimitter
100136 /// </summary>
101137 public class DefaltIKLimitter : IIKLimitter
@@ -104,9 +140,15 @@
104140 /// 総合稼働軸制限一覧
105141 /// </summary>
106142 /// <remarks>ボーン名マッチング用の正規表現オブジェクトと許可回転軸(親ボーン基準)</remarks>
107- Dictionary<string, RotationLimit> TotalRotationLimits { get; set; }
143+ Dictionary<string, RotationLimit> TotalRotationLimits { get; set; }
108144
109145 /// <summary>
146+ /// IK補正回転軸制限一覧
147+ /// </summary>
148+ /// <remarks>IK計算をする際の回転軸の制限</remarks>
149+ Dictionary<string, RotationAxisLimit> RotationAxisLimits { get; set; }
150+
151+ /// <summary>
110152 /// 既定のコンストラクタ
111153 /// </summary>
112154 public DefaltIKLimitter()
@@ -134,7 +176,20 @@
134176 limit.Mirror[0] = true;
135177 limit.Restitution[0] = 0.99f;
136178 TotalRotationLimits.Add("右ひざ", limit);
137-
179+
180+ RotationAxisLimits = new Dictionary<string, RotationAxisLimit>();
181+ RotationAxisLimit axisLimit;
182+ axisLimit = new RotationAxisLimit();
183+ axisLimit.Limits[0] = false;
184+ axisLimit.Limits[1] = true;
185+ axisLimit.Limits[2] = false;
186+ RotationAxisLimits.Add("左足", axisLimit);
187+ axisLimit = new RotationAxisLimit();
188+ axisLimit.Limits[0] = false;
189+ axisLimit.Limits[1] = true;
190+ axisLimit.Limits[2] = false;
191+ RotationAxisLimits.Add("右足", axisLimit);
192+
138193 //IKのソルブ及びそれの調整計算に関するメモ
139194 //上記数値調整計算及び各種数値設定はMMDの元コード推定(リバースエンジニアリング、逆コンパイラとかはしてないからRエンジニアって言うのか分からないけど)する過程で落ち着いている今のところの解です。
140195 //ほんとの解法は樋口さんが知ってるんだろうけどw
@@ -149,10 +204,18 @@
149204 //そのために"反発係数"なる謎なパラメータを付けてますw
150205 //また、解がほとんどまっすぐな解を出す際に、|な感じの解で固定されてしまう問題があるため、3度ぐらい下限を入れています(どうも、MMDの方も入れてるっぽいけど、よく分からない……)
151206 //これは現在の推定結果です。もっと再現性が高い解があれば、改造して、ぜひ教えてください
207+
208+ //2012/01/19追記分
209+ //IK計算の本家MMDとの微妙なズレを発見。
210+ //場所は付属モーション(true my heart)の腰振りのあと\(^o^)/な動作に移行する腰振りのところ
211+ //足の動きが微妙に本家とズレていることを発見
212+ //原因を調査したところ、右足、左足のY軸回転の動きがIKの計算により補正されてしまうのが原因と判明
213+ //そのため、新たにaxisLimit機能を追加し、右足、左足がIK計算でY軸回転を補正されないようにした。
214+ //これにより他のモーションに影響が出ないかは現在調査中
152215 }
153216
154-
155217
218+
156219 #region IIKLimitter メンバー
157220 /// <summary>
158221 /// 制限の適用
@@ -198,8 +261,22 @@
198261 else
199262 bone.LocalTransform.Rotation = MMDXMath.CreateQuaternionFromYawPitchRoll(YRot, XRot, ZRot);
200263
201- }
264+ }
202265
203266 #endregion
267+
268+ /// <summary>
269+ /// 回転軸制限の適用
270+ /// </summary>
271+ /// <param name="boneName">ボーン名</param>
272+ /// <param name="rotationAxis">回転軸</param>
273+ public void Adjust(string boneName, ref Vector3 rotationAxis)
274+ {
275+ RotationAxisLimit limit;
276+ if (RotationAxisLimits.TryGetValue(boneName, out limit))
277+ {
278+ limit.Adjust(ref rotationAxis);
279+ }
280+ }
204281 }
205282 }
--- trunk/MikuMikuDanceCore/Misc/CCDSolver.cs (revision 921)
+++ trunk/MikuMikuDanceCore/Misc/CCDSolver.cs (revision 922)
@@ -97,24 +97,13 @@
9797 if (rotationAngle < -MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1))
9898 rotationAngle = -MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1);
9999
100+ // 回転軸
101+ Vector3 rotationAxis = Vector3.Cross(basis2Effector, basis2Target);
102+ MMDCore.Instance.IKLimitter.Adjust(node.Name, ref rotationAxis);
103+ rotationAxis.Normalize();
100104
101- if (!float.IsNaN(rotationAngle) && rotationAngle > 1.0e-3f)
105+ if (!float.IsNaN(rotationAngle) && rotationAngle > 1.0e-3f && !MMDXMath.CheckNaN(rotationAxis))
102106 {
103- // 回転軸
104- Vector3 rotationAxis = Vector3.Cross(basis2Effector, basis2Target);
105- if (node.Name == "左足" || node.Name == "右足")
106- {
107- rotationAxis.Y = 0;
108- }
109-#if DEBUG
110- if (MMDXMath.CheckNaN(rotationAxis))
111- throw new Exception();
112-#endif
113- rotationAxis.Normalize();
114-#if DEBUG
115- if (MMDXMath.CheckNaN(rotationAxis))
116- throw new Exception();
117-#endif
118107 // 関節回転量の補正
119108 Quaternion subRot = MMDXMath.CreateQuaternionFromAxisAngle(rotationAxis, rotationAngle);
120109 Quaternion.Multiply(ref subRot, ref node.LocalTransform.Rotation, out node.LocalTransform.Rotation);
--- trunk/MikuMikuDanceCore/Misc/IIKLimitter.cs (revision 921)
+++ trunk/MikuMikuDanceCore/Misc/IIKLimitter.cs (revision 922)
@@ -3,6 +3,7 @@
33 using System.Linq;
44 using System.Text;
55 using MikuMikuDance.Core.Model;
6+using Microsoft.Xna.Framework;
67
78 namespace MikuMikuDance.Core.Misc
89 {
@@ -16,5 +17,11 @@
1617 /// </summary>
1718 /// <param name="bone">対象となるボーン</param>
1819 void Adjust(MMDBone bone);
20+ /// <summary>
21+ /// 回転軸制限の適用
22+ /// </summary>
23+ /// <param name="boneName">対象となるボーン名</param>
24+ /// <param name="rotationAxis">回転軸</param>
25+ void Adjust(string boneName, ref Vector3 rotationAxis);
1926 }
2027 }
Show on old repository browser