// 線形補間 public static FloatKeyframe Lerp(FloatKeyframe from, FloatKeyframe to, Vector2 t) { return(new FloatKeyframe( Mathf.Lerp(from.time, to.time, t.x), Mathf.Lerp(from.value, to.value, t.y) )); }
// ベジェを線形補間で近似したキーフレームを追加する public static void AddBezierKeyframes(byte[] interpolation, int type, FloatKeyframe prev_keyframe, FloatKeyframe cur_keyframe, int interpolationQuality, ref FloatKeyframe[] keyframes, ref int index) { if (prev_keyframe == null || IsLinear(interpolation, type)) { keyframes[index++] = cur_keyframe; } else { Vector2 bezierHandleA = GetBezierHandle(interpolation, type, 0); Vector2 bezierHandleB = GetBezierHandle(interpolation, type, 1); int sampleCount = interpolationQuality; for (int j = 0; j < sampleCount; j++) { float t = (j + 1) / (float)sampleCount; Vector2 sample = SampleBezier(bezierHandleA, bezierHandleB, t); keyframes[index++] = FloatKeyframe.Lerp(prev_keyframe, cur_keyframe, sample); } } }
// 移動のみの抽出 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); } }