• R/O
  • SSH
  • HTTPS

mmd-for-unity: コミット


コミットメタ情報

リビジョン129 (tree)
日時2013-05-17 22:26:13
作者novogrammer

ログメッセージ

VMDConverter CreateKeysForRotation
VMDConverter CreateKeysForLocation
 Interpolation Qualityというパラメータ(1〜10)を新設し、
 設定した数で補間曲線を線分に分割するように変更

変更サマリ

差分

--- trunk/MikuMikuDance for Unity/MMDLoader/VMDLoaderWindow.cs (revision 128)
+++ trunk/MikuMikuDance for Unity/MMDLoader/VMDLoaderWindow.cs (revision 129)
@@ -7,6 +7,7 @@
77 Object vmdFile;
88 GameObject pmdPrefab;
99 bool createAnimationFile;
10+ int interpolationQuality;
1011
1112 [MenuItem ("Plugins/MMD Loader/VMD Loader")]
1213 static void Init() {
@@ -16,20 +17,29 @@
1617
1718 void OnGUI() {
1819 const int height = 20;
19-
20+ int top = 0;
21+
2022 pmdPrefab = EditorGUI.ObjectField(
21- new Rect(0, 0, position.width - 16, height), "PMD Prefab", pmdPrefab, typeof(GameObject), false) as GameObject;
23+ new Rect(0, top, position.width - 16, height), "PMD Prefab", pmdPrefab, typeof(GameObject), false) as GameObject;
24+ top += height + 2;
25+
2226 vmdFile = EditorGUI.ObjectField(
23- new Rect(0, height + 2, position.width - 16, height), "VMD File", vmdFile, typeof(Object), false);
24- createAnimationFile = EditorGUI.Toggle(
25- new Rect(0, height * 2 + 4, position.width - 16, height), "Create Asset", createAnimationFile);
27+ new Rect(0, top, position.width - 16, height), "VMD File", vmdFile, typeof(Object), false);
28+ top += height + 2;
29+
30+ createAnimationFile = EditorGUI.Toggle(
31+ new Rect(0, top, position.width - 16, height), "Create Asset", createAnimationFile);
32+ top += height + 2;
2633
34+ interpolationQuality=EditorGUI.IntSlider (
35+ new Rect(0, top, position.width - 16, height), "Interpolation Quality", interpolationQuality, 1, 10);
36+ top += height + 2;
2737
2838 if (pmdPrefab != null && vmdFile != null)
2939 {
30- if (GUI.Button(new Rect(0, height * 3 + 6, position.width / 2, 16), "Convert"))
40+ if (GUI.Button(new Rect(0, top, position.width / 2, 16), "Convert"))
3141 {
32- new VMDLoaderScript(vmdFile, pmdPrefab, createAnimationFile);
42+ new VMDLoaderScript(vmdFile, pmdPrefab, createAnimationFile,interpolationQuality);
3343 vmdFile = null;
3444 }
3545 }
@@ -36,11 +46,11 @@
3646 else
3747 {
3848 if (pmdPrefab == null)
39- EditorGUI.LabelField(new Rect(0, height * 3 + 6, position.width, height), "Missing", "Select PMD Prefab");
49+ EditorGUI.LabelField(new Rect(0, top, position.width, height), "Missing", "Select PMD Prefab");
4050 else if (vmdFile == null)
41- EditorGUI.LabelField(new Rect(0, height * 3 + 6, position.width, height), "Missing", "Select VMD File");
51+ EditorGUI.LabelField(new Rect(0, top, position.width, height), "Missing", "Select VMD File");
4252 else
43- EditorGUI.LabelField(new Rect(0, height * 3 + 6, position.width, height), "Missing", "Select PMD and VMD");
53+ EditorGUI.LabelField(new Rect(0, top, position.width, height), "Missing", "Select PMD and VMD");
4454 }
4555 }
4656 }
--- trunk/MikuMikuDance for Unity/MMDLoader/Private/VMDLoaderScript.cs (revision 128)
+++ trunk/MikuMikuDance for Unity/MMDLoader/Private/VMDLoaderScript.cs (revision 129)
@@ -15,6 +15,7 @@
1515 public GameObject assign_pmd; // 適用したいPMDファイル
1616 public string clip_name; // クリップの名前
1717 public bool create_asset;
18+ public int interpolationQuality;// 補間曲線の品質(近似する線分の数)
1819
1920 BinaryReader LoadFile(Object obj, string path)
2021 {
@@ -37,11 +38,12 @@
3738 }
3839
3940 // Use this for initialization
40- public VMDLoaderScript(Object vmdFile, GameObject assignPmdPrefab, bool createAsset)
41+ public VMDLoaderScript(Object vmdFile, GameObject assignPmdPrefab, bool createAsset, int interpolationQuality)
4142 {
4243 this.vmd = vmdFile;
4344 this.assign_pmd = assignPmdPrefab;
4445 this.create_asset = createAsset;
46+ this.interpolationQuality = interpolationQuality;
4547
4648 if (this.vmd != null)
4749 LoadVMDFile();
@@ -55,7 +57,7 @@
5557 void BurnUnityFormatForVMD(MMD.VMD.VMDFormat format)
5658 {
5759 MMD.VMD.VMDConverter conv = new MMD.VMD.VMDConverter();
58- conv.CreateAnimationClip(format, this.assign_pmd, this.anim, this.create_asset);
60+ conv.CreateAnimationClip(format, this.assign_pmd, this.anim, this.create_asset, this.interpolationQuality);
5961 }
6062 }
6163 #endif
\ No newline at end of file
--- trunk/MikuMikuDance for Unity/MMDLoader/Private/MMDConverter.cs (revision 128)
+++ trunk/MikuMikuDance for Unity/MMDLoader/Private/MMDConverter.cs (revision 129)
@@ -864,25 +864,148 @@
864864 {
865865 public class VMDConverter
866866 {
867- // tangentを求める
868- // 今は使ってないので注意
869- float GetTangent(byte[] interpolation, int type, int ab)
867+ // ベジェハンドルを取得する
868+ // 0~127の値を 0f~1fとして返す
869+ static Vector2 GetBezierHandle(byte[] interpolation, int type, int ab)
870870 {
871871 // 0=X, 1=Y, 2=Z, 3=R
872872 // abはa?かb?のどちらを使いたいか
873- Vector2 itpl = new Vector2((float)interpolation[ab*8+type], (float)interpolation[ab*8+4+type]);
874- if (ab == 1) {
875- // わからんけどマイナスになるので直す
876- itpl.x = -(itpl.x-128f);
877- itpl.y = -(itpl.y-128f);
873+ Vector2 bezierHandle = new Vector2((float)interpolation[ab*8+type], (float)interpolation[ab*8+4+type]);
874+ return bezierHandle/127f;
875+ }
876+ // p0:(0f,0f),p3:(1f,1f)のベジェ曲線上の点を取得する
877+ // tは0~1の範囲
878+ static Vector2 SampleBezier(Vector2 bezierHandleA, Vector2 bezierHandleB, float t)
879+ {
880+ Vector2 p0 = Vector2.zero;
881+ Vector2 p1 = bezierHandleA;
882+ Vector2 p2 = bezierHandleB;
883+ Vector2 p3 = new Vector2(1f,1f);
884+
885+ Vector2 q0 = Vector2.Lerp(p0, p1, t);
886+ Vector2 q1 = Vector2.Lerp(p1, p2, t);
887+ Vector2 q2 = Vector2.Lerp(p2, p3, t);
888+
889+ Vector2 r0 = Vector2.Lerp(q0, q1, t);
890+ Vector2 r1 = Vector2.Lerp(q1, q2, t);
891+
892+ Vector2 s0 = Vector2.Lerp(r0, r1, t);
893+ return s0;
894+ }
895+ // 補間曲線が線形補間と等価か
896+ static bool IsLinear(byte[] interpolation, int type)
897+ {
898+ byte ax=interpolation[0*8+type];
899+ byte ay=interpolation[0*8+4+type];
900+ byte bx=interpolation[1*8+type];
901+ byte by=interpolation[1*8+4+type];
902+ return (ax == ay) && (bx == by);
903+ }
904+ // 補間曲線の近似のために追加するキーフレームを含めたキーフレーム数を取得する
905+ int GetKeyframeCount(List<MMD.VMD.VMDFormat.Motion> mlist, int type, int interpolationQuality)
906+ {
907+ int count = 0;
908+ for(int i = 0; i < mlist.Count; i++)
909+ {
910+ if(i>0 && !IsLinear(mlist[i].interpolation, type))
911+ {
912+ count += interpolationQuality;//Interpolation Keyframes
913+ }
914+ else
915+ {
916+ count += 1;//Keyframe
917+ }
878918 }
879- itpl.Normalize();
919+ return count;
920+ }
921+ // 任意の型のvalueを持つキーフレーム
922+ abstract class CustomKeyframe<Type>
923+ {
924+ public CustomKeyframe(float time,Type value)
925+ {
926+ this.time=time;
927+ this.value=value;
928+ }
929+ public float time{ get; set; }
930+ public Type value{ get; set; }
931+ }
932+ // float型のvalueを持つキーフレーム
933+ class FloatKeyframe:CustomKeyframe<float>
934+ {
935+ public FloatKeyframe(float time,float value):base(time,value)
936+ {
937+ }
938+ // 線形補間
939+ public static FloatKeyframe Lerp(FloatKeyframe from, FloatKeyframe to,Vector2 t)
940+ {
941+ return new FloatKeyframe(
942+ Mathf.Lerp(from.time,to.time,t.x),
943+ Mathf.Lerp(from.value,to.value,t.y)
944+ );
945+ }
946+ // ベジェを線形補間で近似したキーフレームを追加する
947+ public static void AddBezierKeyframes(byte[] interpolation, int type,
948+ FloatKeyframe prev_keyframe,FloatKeyframe cur_keyframe, int interpolationQuality,
949+ ref FloatKeyframe[] keyframes,ref int index)
950+ {
951+ if(prev_keyframe==null || IsLinear(interpolation,type))
952+ {
953+ keyframes[index++]=cur_keyframe;
954+ }
955+ else
956+ {
957+ Vector2 bezierHandleA=GetBezierHandle(interpolation,type,0);
958+ Vector2 bezierHandleB=GetBezierHandle(interpolation,type,1);
959+ int sampleCount = interpolationQuality;
960+ for(int j = 0; j < sampleCount; j++)
961+ {
962+ float t = (j+1)/(float)sampleCount;
963+ Vector2 sample = SampleBezier(bezierHandleA,bezierHandleB,t);
964+ keyframes[index++] = FloatKeyframe.Lerp(prev_keyframe,cur_keyframe,sample);
965+ }
966+ }
967+ }
968+ }
969+ // Quaternion型のvalueを持つキーフレーム
970+ class QuaternionKeyframe:CustomKeyframe<Quaternion>
971+ {
972+ public QuaternionKeyframe(float time,Quaternion value):base(time,value)
973+ {
974+ }
975+ // 線形補間
976+ public static QuaternionKeyframe Lerp(QuaternionKeyframe from, QuaternionKeyframe to,Vector2 t)
977+ {
978+ return new QuaternionKeyframe(
979+ Mathf.Lerp(from.time,to.time,t.x),
980+ Quaternion.Slerp(from.value,to.value,t.y)
981+ );
982+ }
983+ // ベジェを線形補間で近似したキーフレームを追加する
984+ public static void AddBezierKeyframes(byte[] interpolation, int type,
985+ QuaternionKeyframe prev_keyframe,QuaternionKeyframe cur_keyframe, int interpolationQuality,
986+ ref QuaternionKeyframe[] keyframes,ref int index)
987+ {
988+ if(prev_keyframe==null || IsLinear(interpolation,type))
989+ {
990+ keyframes[index++]=cur_keyframe;
991+ }
992+ else
993+ {
994+ Vector2 bezierHandleA=GetBezierHandle(interpolation,type,0);
995+ Vector2 bezierHandleB=GetBezierHandle(interpolation,type,1);
996+ int sampleCount = interpolationQuality;
997+ for(int j = 0; j < sampleCount; j++)
998+ {
999+ float t=(j+1)/(float)sampleCount;
1000+ Vector2 sample = SampleBezier(bezierHandleA,bezierHandleB,t);
1001+ keyframes[index++] = QuaternionKeyframe.Lerp(prev_keyframe,cur_keyframe,sample);
1002+ }
1003+ }
1004+ }
8801005
881- //Vector2 r = Vector2.right;
882- //return (Vector2.Dot(itpl, r) * Mathf.PI) * 180.0f / Mathf.PI;
883- return 0;
8841006 }
885- //移動の線形補間用tangentを求める
1007+
1008+ //移動の線形補間用tangentを求める
8861009 float GetLinearTangentForPosition(Keyframe from_keyframe,Keyframe to_keyframe)
8871010 {
8881011 return (to_keyframe.value-from_keyframe.value)/(to_keyframe.time-from_keyframe.time);
@@ -911,55 +1034,70 @@
9111034 }
9121035 //アニメーションエディタでBothLinearを選択したときの値
9131036 private const int TangentModeBothLinear=21;
1037+
1038+ //UnityのKeyframeに変換する(回転用)
1039+ void ToKeyframesForRotation(QuaternionKeyframe[] custom_keys,ref Keyframe[] rx_keys,ref Keyframe[] ry_keys,ref Keyframe[] rz_keys)
1040+ {
1041+ rx_keys=new Keyframe[custom_keys.Length];
1042+ ry_keys=new Keyframe[custom_keys.Length];
1043+ rz_keys=new Keyframe[custom_keys.Length];
1044+ for(int i = 0; i < custom_keys.Length; i++)
1045+ {
1046+ //オイラー角を取り出す
1047+ Vector3 eulerAngles=custom_keys[i].value.eulerAngles;
1048+ rx_keys[i]=new Keyframe(custom_keys[i].time,eulerAngles.x);
1049+ ry_keys[i]=new Keyframe(custom_keys[i].time,eulerAngles.y);
1050+ rz_keys[i]=new Keyframe(custom_keys[i].time,eulerAngles.z);
1051+ //線形補間する
1052+ rx_keys[i].tangentMode=TangentModeBothLinear;
1053+ ry_keys[i].tangentMode=TangentModeBothLinear;
1054+ rz_keys[i].tangentMode=TangentModeBothLinear;
1055+ if(i>0)
1056+ {
1057+ float tx=GetLinearTangentForRotation(rx_keys[i-1],rx_keys[i]);
1058+ float ty=GetLinearTangentForRotation(ry_keys[i-1],ry_keys[i]);
1059+ float tz=GetLinearTangentForRotation(rz_keys[i-1],rz_keys[i]);
1060+ rx_keys[i-1].outTangent=tx;
1061+ ry_keys[i-1].outTangent=ty;
1062+ rz_keys[i-1].outTangent=tz;
1063+ rx_keys[i].inTangent=tx;
1064+ ry_keys[i].inTangent=ty;
1065+ rz_keys[i].inTangent=tz;
1066+ }
1067+ }
1068+ }
1069+
1070+
9141071 // あるボーンに含まれるキーフレを抽出
9151072 // これは回転のみ
916- void CreateKeysForRotation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path)
1073+ void CreateKeysForRotation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path, int interpolationQuality)
9171074 {
9181075 try
9191076 {
9201077 List<MMD.VMD.VMDFormat.Motion> mlist = format.motion_list.motion[current_bone];
921-
922- Keyframe[] rx_keys = new Keyframe[mlist.Count];
923- Keyframe[] ry_keys = new Keyframe[mlist.Count];
924- Keyframe[] rz_keys = new Keyframe[mlist.Count];
1078+ int keyframeCount = GetKeyframeCount(mlist, 3, interpolationQuality);
1079+
1080+ QuaternionKeyframe[] r_keys = new QuaternionKeyframe[keyframeCount];
1081+ QuaternionKeyframe r_prev_key=null;
1082+ int ir=0;
9251083 for (int i = 0; i < mlist.Count; i++)
9261084 {
9271085 const float tick_time = 1.0f / 30.0f;
9281086 float tick = mlist[i].flame_no * tick_time;
929- float a = GetTangent(mlist[i].interpolation, 3, 0); // inTangent
930- float b; // outTangent
9311087
932- // -1フレにはoutTangentは存在しないのでcatch
933- try { b = GetTangent(mlist[i-1].interpolation, 3, 1); }
934- catch { b = 0; }
935- //オイラー角を取り出す
936- Vector3 eulerAngles=mlist[i].rotation.eulerAngles;
937- rx_keys[i] = new Keyframe(tick, eulerAngles.x, a, b);
938- ry_keys[i] = new Keyframe(tick, eulerAngles.y, a, b);
939- rz_keys[i] = new Keyframe(tick, eulerAngles.z, a, b);
940-
941- //GetTangentが常に0を返すため、応急処置として線形補間する
942- rx_keys[i].tangentMode=TangentModeBothLinear;
943- ry_keys[i].tangentMode=TangentModeBothLinear;
944- rz_keys[i].tangentMode=TangentModeBothLinear;
945- if(i>0)
946- {
947- float tx=GetLinearTangentForRotation(rx_keys[i-1],rx_keys[i]);
948- float ty=GetLinearTangentForRotation(ry_keys[i-1],ry_keys[i]);
949- float tz=GetLinearTangentForRotation(rz_keys[i-1],rz_keys[i]);
950- rx_keys[i-1].outTangent=tx;
951- ry_keys[i-1].outTangent=ty;
952- rz_keys[i-1].outTangent=tz;
953- rx_keys[i].inTangent=tx;
954- ry_keys[i].inTangent=ty;
955- rz_keys[i].inTangent=tz;
956- }
1088+ Quaternion rotation=mlist[i].rotation;
1089+ QuaternionKeyframe r_cur_key=new QuaternionKeyframe(tick,rotation);
1090+ QuaternionKeyframe.AddBezierKeyframes(mlist[i].interpolation,3,r_prev_key,r_cur_key,interpolationQuality,ref r_keys,ref ir);
1091+ r_prev_key=r_cur_key;
9571092 }
958-
1093+
1094+ Keyframe[] rx_keys=null;
1095+ Keyframe[] ry_keys=null;
1096+ Keyframe[] rz_keys=null;
1097+ ToKeyframesForRotation(r_keys, ref rx_keys, ref ry_keys, ref rz_keys);
9591098 AnimationCurve curve_x = new AnimationCurve(rx_keys);
9601099 AnimationCurve curve_y = new AnimationCurve(ry_keys);
9611100 AnimationCurve curve_z = new AnimationCurve(rz_keys);
962-
9631101 // ここで回転オイラー角をセット(補間はクォータニオン)
9641102 AnimationUtility.SetEditorCurve(clip,bone_path,typeof(Transform),"localEulerAngles.x",curve_x);
9651103 AnimationUtility.SetEditorCurve(clip,bone_path,typeof(Transform),"localEulerAngles.y",curve_y);
@@ -970,9 +1108,26 @@
9701108 //Debug.LogError("互換性のないボーンが読み込まれました:" + bone_path);
9711109 }
9721110 }
973-
1111+ //UnityのKeyframeに変換する(移動用)
1112+ Keyframe[] ToKeyframesForLocation(FloatKeyframe[] custom_keys)
1113+ {
1114+ Keyframe[] keys=new Keyframe[custom_keys.Length];
1115+ for(int i = 0; i < custom_keys.Length; i++)
1116+ {
1117+ keys[i]=new Keyframe(custom_keys[i].time,custom_keys[i].value);
1118+ //線形補間する
1119+ keys[i].tangentMode=TangentModeBothLinear;
1120+ if(i>0)
1121+ {
1122+ float t=GetLinearTangentForPosition(keys[i-1],keys[i]);
1123+ keys[i-1].outTangent=t;
1124+ keys[i].inTangent=t;
1125+ }
1126+ }
1127+ return keys;
1128+ }
9741129 // 移動のみの抽出
975- void CreateKeysForLocation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path, GameObject current_obj = null)
1130+ void CreateKeysForLocation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path, int interpolationQuality, GameObject current_obj = null)
9761131 {
9771132 try
9781133 {
@@ -982,53 +1137,46 @@
9821137
9831138 List<MMD.VMD.VMDFormat.Motion> mlist = format.motion_list.motion[current_bone];
9841139
985- Keyframe[] lx_keys = new Keyframe[mlist.Count];
986- Keyframe[] ly_keys = new Keyframe[mlist.Count];
987- Keyframe[] lz_keys = new Keyframe[mlist.Count];
1140+ int keyframeCountX = GetKeyframeCount(mlist, 0, interpolationQuality);
1141+ int keyframeCountY = GetKeyframeCount(mlist, 1, interpolationQuality);
1142+ int keyframeCountZ = GetKeyframeCount(mlist, 2, interpolationQuality);
1143+
1144+ FloatKeyframe[] lx_keys = new FloatKeyframe[keyframeCountX];
1145+ FloatKeyframe[] ly_keys = new FloatKeyframe[keyframeCountY];
1146+ FloatKeyframe[] lz_keys = new FloatKeyframe[keyframeCountZ];
1147+
1148+ FloatKeyframe lx_prev_key=null;
1149+ FloatKeyframe ly_prev_key=null;
1150+ FloatKeyframe lz_prev_key=null;
1151+ int ix=0;
1152+ int iy=0;
1153+ int iz=0;
9881154 for (int i = 0; i < mlist.Count; i++)
9891155 {
9901156 const float tick_time = 1.0f / 30.0f;
9911157
9921158 float tick = mlist[i].flame_no * tick_time;
993- float a_x, a_y, a_z, b_x, b_y, b_z;
9941159
1160+ FloatKeyframe lx_cur_key=new FloatKeyframe(tick,mlist[i].location.x + default_position.x);
1161+ FloatKeyframe ly_cur_key=new FloatKeyframe(tick,mlist[i].location.y + default_position.y);
1162+ FloatKeyframe lz_cur_key=new FloatKeyframe(tick,mlist[i].location.z + default_position.z);
1163+
9951164 // 各軸別々に補間が付いてる
996- a_x = GetTangent(mlist[i].interpolation, 0, 0);
997- a_y = GetTangent(mlist[i].interpolation, 1, 0);
998- a_z = GetTangent(mlist[i].interpolation, 2, 0);
999- b_x = GetTangent(mlist[i].interpolation, 0, 1);
1000- b_y = GetTangent(mlist[i].interpolation, 1, 1);
1001- b_z = GetTangent(mlist[i].interpolation, 2, 1);
1165+ FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation,0,lx_prev_key,lx_cur_key,interpolationQuality,ref lx_keys,ref ix);
1166+ FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation,1,ly_prev_key,ly_cur_key,interpolationQuality,ref ly_keys,ref iy);
1167+ FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation,2,lz_prev_key,lz_cur_key,interpolationQuality,ref lz_keys,ref iz);
10021168
1003- lx_keys[i]=(new Keyframe(tick, mlist[i].location.x + default_position.x, a_x, b_x));
1004- ly_keys[i]=(new Keyframe(tick, mlist[i].location.y + default_position.y, a_y, b_y));
1005- lz_keys[i]=(new Keyframe(tick, mlist[i].location.z + default_position.z, a_z, b_z));
1006-
1007- //GetTangentが常に0を返すため、応急処置として線形補間する
1008- lx_keys[i].tangentMode=TangentModeBothLinear;
1009- ly_keys[i].tangentMode=TangentModeBothLinear;
1010- lz_keys[i].tangentMode=TangentModeBothLinear;
1011- if(i>0)
1012- {
1013- float tx=GetLinearTangentForPosition(lx_keys[i-1],lx_keys[i]);
1014- float ty=GetLinearTangentForPosition(ly_keys[i-1],ly_keys[i]);
1015- float tz=GetLinearTangentForPosition(lz_keys[i-1],lz_keys[i]);
1016- lx_keys[i-1].outTangent=tx;
1017- ly_keys[i-1].outTangent=ty;
1018- lz_keys[i-1].outTangent=tz;
1019- lx_keys[i].inTangent=tx;
1020- ly_keys[i].inTangent=ty;
1021- lz_keys[i].inTangent=tz;
1022- }
1023-
1169+ lx_prev_key=lx_cur_key;
1170+ ly_prev_key=ly_cur_key;
1171+ lz_prev_key=lz_cur_key;
10241172 }
10251173
10261174 // 回転ボーンの場合はデータが入ってないはず
10271175 if (mlist.Count != 0)
10281176 {
1029- AnimationCurve curve_x = new AnimationCurve(lx_keys);
1030- AnimationCurve curve_y = new AnimationCurve(ly_keys);
1031- AnimationCurve curve_z = new AnimationCurve(lz_keys);
1177+ AnimationCurve curve_x = new AnimationCurve(ToKeyframesForLocation(lx_keys));
1178+ AnimationCurve curve_y = new AnimationCurve(ToKeyframesForLocation(ly_keys));
1179+ AnimationCurve curve_z = new AnimationCurve(ToKeyframesForLocation(lz_keys));
10321180 AnimationUtility.SetEditorCurve(clip,bone_path,typeof(Transform),"m_LocalPosition.x",curve_x);
10331181 AnimationUtility.SetEditorCurve(clip,bone_path,typeof(Transform),"m_LocalPosition.y",curve_y);
10341182 AnimationUtility.SetEditorCurve(clip,bone_path,typeof(Transform),"m_LocalPosition.z",curve_z);
@@ -1114,7 +1262,7 @@
11141262 }
11151263
11161264 // 無駄なカーブを登録してるけどどうするか
1117- void FullEntryBoneAnimation(MMD.VMD.VMDFormat format, AnimationClip clip, Dictionary<string, string> dic, Dictionary<string, GameObject> obj)
1265+ void FullEntryBoneAnimation(MMD.VMD.VMDFormat format, AnimationClip clip, Dictionary<string, string> dic, Dictionary<string, GameObject> obj, int interpolationQuality)
11181266 {
11191267 foreach (KeyValuePair<string, string> p in dic) // keyはtransformの名前, valueはパス
11201268 {
@@ -1132,8 +1280,8 @@
11321280 }
11331281
11341282 // キーフレの登録
1135- CreateKeysForLocation(format, clip, p.Key, p.Value, current_obj);
1136- CreateKeysForRotation(format, clip, p.Key, p.Value);
1283+ CreateKeysForLocation(format, clip, p.Key, p.Value, interpolationQuality, current_obj);
1284+ CreateKeysForRotation(format, clip, p.Key, p.Value, interpolationQuality);
11371285 }
11381286 }
11391287
@@ -1159,7 +1307,7 @@
11591307 }
11601308
11611309 // クリップをアニメーションに登録する
1162- public void CreateAnimationClip(MMD.VMD.VMDFormat format, GameObject assign_pmd, Animation anim, bool create_asset)
1310+ public void CreateAnimationClip(MMD.VMD.VMDFormat format, GameObject assign_pmd, Animation anim, bool create_asset, int interpolationQuality)
11631311 {
11641312 //Animation anim = assign_pmd.GetComponent<Animation>();
11651313
@@ -1171,7 +1319,7 @@
11711319 Dictionary<string, GameObject> gameobj = new Dictionary<string, GameObject>();
11721320 GetGameObjects(gameobj, assign_pmd); // 親ボーン下のGameObjectを取得
11731321 FullSearchBonePath(assign_pmd.transform, bone_path);
1174- FullEntryBoneAnimation(format, clip, bone_path, gameobj);
1322+ FullEntryBoneAnimation(format, clip, bone_path, gameobj, interpolationQuality);
11751323
11761324 CreateKeysForSkin(format, clip); // 表情の追加
11771325
旧リポジトリブラウザで表示