// 無駄なカーブを登録してるけどどうするか void FullEntryBoneAnimation(MMD.VMD.VMDFormat format, AnimationClip clip, Dictionary <string, string> dic, Dictionary <string, GameObject> obj, int interpolationQuality) { foreach (KeyValuePair <string, List <MMD.VMD.VMDFormat.Motion> > p in format.motion_list.motion) { // 互いに名前の一致する場合にRigidbodyが存在するか調べたい GameObject current_obj = null; string bonePath = null; // keyはtransformの名前, valueはパス if (dic.TryGetValue(p.Key, out bonePath)) { current_obj = obj[p.Key]; // Rigidbodyがある場合はキーフレの登録を無視する var rigid = current_obj.GetComponent <Rigidbody>(); if (rigid != null && !rigid.isKinematic) { continue; } } // キーフレの登録 //CreateKeysForLocation(format, clip, p.Key, bonePath, interpolationQuality, current_obj); CreateKeysForRotation(format, clip, p.Key, bonePath, interpolationQuality); } }
// クリップをアニメーションに登録する private AnimationClip CreateAnimationClip_(MMD.VMD.VMDFormat format, GameObject assign_pmd, int interpolationQuality) { //スケール設定 scale_ = 1.0f; if (!assign_pmd) { return(null); } MMDEngine engine = assign_pmd.GetComponent <MMDEngine>(); if (!engine) { return(null); } scale_ = engine.scale; //Animation anim = assign_pmd.GetComponent<Animation>(); // クリップの作成 AnimationClip clip = new AnimationClip(); clip.name = assign_pmd.name + "_" + format.name; Dictionary <string, string> bone_path = new Dictionary <string, string>(); Dictionary <string, GameObject> gameobj = new Dictionary <string, GameObject>(); GetGameObjects(gameobj, assign_pmd); // 親ボーン下のGameObjectを取得 FullSearchBonePath(assign_pmd.transform, bone_path); FullEntryBoneAnimation(format, clip, bone_path, gameobj, interpolationQuality); CreateKeysForSkin(format, clip); // 表情の追加 return(clip); }
// あるボーンに含まれるキーフレを抽出 // これは回転のみ void CreateKeysForRotation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path, int interpolationQuality) { try { List <MMD.VMD.VMDFormat.Motion> mlist = format.motion_list.motion[current_bone]; int keyframeCount = GetKeyframeCount(mlist, 3, interpolationQuality); QuaternionKeyframe[] r_keys = new QuaternionKeyframe[keyframeCount]; QuaternionKeyframe r_prev_key = null; int ir = 0; for (int i = 0; i < mlist.Count; i++) { const float tick_time = 1.0f / 30.0f; float tick = mlist[i].flame_no * tick_time; Quaternion rotation = mlist[i].rotation; QuaternionKeyframe r_cur_key = new QuaternionKeyframe(tick, rotation); QuaternionKeyframe.AddBezierKeyframes(mlist[i].interpolation, 3, r_prev_key, r_cur_key, interpolationQuality, ref r_keys, ref ir); r_prev_key = r_cur_key; } Keyframe[] rx_keys = null; Keyframe[] ry_keys = null; Keyframe[] rz_keys = null; ToKeyframesForRotation(r_keys, ref rx_keys, ref ry_keys, ref rz_keys); AnimationCurve curve_x = new AnimationCurve(rx_keys); AnimationCurve curve_y = new AnimationCurve(ry_keys); AnimationCurve curve_z = new AnimationCurve(rz_keys); // ここで回転オイラー角をセット(補間はクォータニオン) #if !UNITY_4_2 //4.3以降 AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "localEulerAngles.x"), curve_x); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "localEulerAngles.y"), curve_y); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "localEulerAngles.z"), curve_z); #else AnimationUtility.SetEditorCurve(clip, bone_path, typeof(Transform), "localEulerAngles.x", curve_x); AnimationUtility.SetEditorCurve(clip, bone_path, typeof(Transform), "localEulerAngles.y", curve_y); AnimationUtility.SetEditorCurve(clip, bone_path, typeof(Transform), "localEulerAngles.z", curve_z); #endif } catch (KeyNotFoundException) { //Debug.LogError("互換性のないボーンが読み込まれました:" + bone_path); } }
// 無駄なカーブを登録してるけどどうするか void FullEntryBoneAnimation(MMD.VMD.VMDFormat format, AnimationClip clip, Dictionary <string, string> dic, Dictionary <string, GameObject> obj, int interpolationQuality) { foreach (KeyValuePair <string, string> p in dic) // keyはtransformの名前, valueはパス { // 互いに名前の一致する場合にRigidbodyが存在するか調べたい GameObject current_obj = null; if (obj.ContainsKey(p.Key)) { current_obj = obj[p.Key]; // Rigidbodyがある場合はキーフレの登録を無視する var rigid = current_obj.GetComponent <Rigidbody>(); if (rigid != null && !rigid.isKinematic) { continue; } } // キーフレの登録 CreateKeysForLocation(format, clip, p.Key, p.Value, interpolationQuality, current_obj); CreateKeysForRotation(format, clip, p.Key, p.Value, interpolationQuality); } }
void CreateKeysForSkin(MMD.VMD.VMDFormat format, AnimationClip clip) { const float tick_time = 1f / 30f; // 全ての表情に打たれているキーフレームを探索 List <VMD.VMDFormat.SkinData> s; foreach (var skin in format.skin_list.skin) { s = skin.Value; Keyframe[] keyframe = new Keyframe[skin.Value.Count]; // キーフレームの登録を行う for (int i = 0; i < skin.Value.Count; i++) { keyframe[i] = new Keyframe(s[i].frame_no * tick_time, s[i].weight); //線形補間する if (i > 0) { float t = GetLinearTangentForPosition(keyframe[i - 1], keyframe[i]); keyframe[i - 1].outTangent = t; keyframe[i].inTangent = t; } } AddDummyKeyframe(ref keyframe); // Z軸移動にキーフレームを打つ AnimationCurve curve = new AnimationCurve(keyframe); for (int i = 0; i < curve.keys.Length; i++) { AnimationUtility.SetKeyLeftTangentMode(curve, i, AnimationUtility.TangentMode.Linear); AnimationUtility.SetKeyRightTangentMode(curve, i, AnimationUtility.TangentMode.Linear); } AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve("Expression/" + skin.Key, typeof(Transform), "m_LocalPosition.z"), curve); } }
void BurnUnityFormatForVMD(MMD.VMD.VMDFormat format) { MMD.VMD.VMDConverter conv = new MMD.VMD.VMDConverter(); conv.CreateAnimationClip(format, this.assign_pmd, this.anim, this.create_asset); }
// 移動のみの抽出 void CreateKeysForLocation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path, int interpolationQuality, GameObject current_obj = null) { try { const float tick_time = 1.0f / VMD_FPS; Vector3 default_position = Vector3.zero; if (current_obj != null) { default_position = current_obj.transform.localPosition; } List <MMD.VMD.VMDFormat.Motion> mlist = format.motion_list.motion[current_bone]; int keyframeCountX = GetKeyframeCount(mlist, 0, interpolationQuality); int keyframeCountY = GetKeyframeCount(mlist, 1, interpolationQuality); int keyframeCountZ = GetKeyframeCount(mlist, 2, interpolationQuality); FloatKeyframe[] lx_keys = new FloatKeyframe[keyframeCountX]; FloatKeyframe[] ly_keys = new FloatKeyframe[keyframeCountY]; FloatKeyframe[] lz_keys = new FloatKeyframe[keyframeCountZ]; FloatKeyframe lx_prev_key = null; FloatKeyframe ly_prev_key = null; FloatKeyframe lz_prev_key = null; int ix = 0; int iy = 0; int iz = 0; for (int i = 0; i < mlist.Count; i++) { float tick = mlist[i].frame_no * tick_time; FloatKeyframe lx_cur_key = new FloatKeyframe(tick, mlist[i].location.x * scale_ + default_position.x); FloatKeyframe ly_cur_key = new FloatKeyframe(tick, mlist[i].location.y * scale_ + default_position.y); FloatKeyframe lz_cur_key = new FloatKeyframe(tick, mlist[i].location.z * scale_ + default_position.z); // 各軸別々に補間が付いてる FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation, 0, lx_prev_key, lx_cur_key, interpolationQuality, ref lx_keys, ref ix); FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation, 1, ly_prev_key, ly_cur_key, interpolationQuality, ref ly_keys, ref iy); FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation, 2, lz_prev_key, lz_cur_key, interpolationQuality, ref lz_keys, ref iz); lx_prev_key = lx_cur_key; ly_prev_key = ly_cur_key; lz_prev_key = lz_cur_key; } // 回転ボーンの場合はデータが入ってないはず if (mlist.Count != 0) { AnimationCurve curve_x = ToAnimationCurveForLocation(lx_keys); AnimationCurve curve_y = ToAnimationCurveForLocation(ly_keys); AnimationCurve curve_z = ToAnimationCurveForLocation(lz_keys); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "m_LocalPosition.x"), curve_x); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "m_LocalPosition.y"), curve_y); AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "m_LocalPosition.z"), curve_z); } } catch (KeyNotFoundException) { Debug.LogError("互換性のないボーンが読み込まれました:" + current_bone); } }