/// <summary> /// Add a new key to the spline at the specified time /// </summary> public void AddKey(float time, Vector3 pos) { CtrlPoint ctrl = new CtrlPoint(); ctrl.mTime = time; ctrl.mVal = pos; ctrl.mTan = Vector3.zero; mIsSmooth = false; int index = 0; for (int i = mCp.Count; i > 0;) { CtrlPoint point = mCp[--i]; if (point.mTime < time) { index = i + 1; break; } } if (index == mCp.Count) { mCp.Add(ctrl); } else { mLastIndex = 0; mLastSample = 0.0f; mCp.Insert(index, ctrl); } }
/// <summary> /// Sample the spline at the specified time /// </summary> public Vector3 Sample(float time, SampleType type) { if (mCp.Count == 0) { return(Vector3.zero); } if (time > front.mTime) { if (time < back.mTime) { if (!mIsSmooth) { Smoothen(); } // Start at the last sampled keyframe if we're sampling forward int i = (mLastSample > time) ? 0 : mLastIndex; // Cache the current sampling time for the next execution mLastSample = time; mLastIndex = mCp.Count - 1; // Run through all control points until the proper time is encountered while (i < mLastIndex) { CtrlPoint current = mCp[i]; CtrlPoint next = mCp[++i]; if (time < next.mTime) { // Remember the current location mLastIndex = i - 1; if (type == SampleType.Floor) { return(current.mVal); } float duration = next.mTime - current.mTime; float factor = (time - current.mTime) / duration; if (type == SampleType.Spline) { return(Interpolation.Hermite( current.mVal, next.mVal, current.mTan, next.mTan, factor, duration)); } return(Interpolation.Linear(current.mVal, next.mVal, factor)); } } } return(back.mVal); } return(front.mVal); }
/// <summary> /// Add a new key to the spline at the specified time /// </summary> public void AddKey(float time, Quaternion rot) { CtrlPoint ctrl = new CtrlPoint(); ctrl.mTime = time; ctrl.mVal = rot; ctrl.mTan = 0.0f; ctrl.mCtrl = rot; mIsSmooth = false; int index = 0; // Find the index where the control point should be added for (int i = mCp.Count; i > 0;) { CtrlPoint point = mCp[--i]; if (point.mTime < time) { index = i + 1; break; } } // Ensure that the rotation always takes the shortest path if (index > 0 && mCp.Count > 0) { CtrlPoint prev = mCp[index - 1]; if (Quaternion.Dot(prev.mVal, ctrl.mVal) < 0.0f) { ctrl.mVal = new Quaternion(-ctrl.mVal.x, -ctrl.mVal.y, -ctrl.mVal.z, -ctrl.mVal.w); ctrl.mCtrl = ctrl.mVal; } } // Add this control point if (index == mCp.Count) { mCp.Add(ctrl); } else { mLastIndex = 0; mLastSample = 0.0f; mCp.Insert(index, ctrl); } }
/// <summary> /// Calculate the spline tangents /// </summary> private void Smoothen() { if (mCp.Count > 2) { for (int current = 1, end = mCp.Count - 1; current < end; ++current) { CtrlPoint ctrlPast = mCp[current - 1]; CtrlPoint ctrlCurrent = mCp[current]; CtrlPoint ctrlFuture = mCp[current + 1]; ctrlCurrent.mTan = Interpolation.GetHermiteTangent( ctrlCurrent.mVal - ctrlPast.mVal, ctrlFuture.mVal - ctrlCurrent.mVal, ctrlCurrent.mTime - ctrlPast.mTime, ctrlFuture.mTime - ctrlCurrent.mTime); } } mIsSmooth = true; }
/// <summary> /// Calculate the spline tangents /// </summary> private void Smoothen() { if (mCp.Count > 2) { for (int current = 1, end = mCp.Count - 1; current < end; ++current) { CtrlPoint ctrlPast = mCp[current - 1]; CtrlPoint ctrlCurrent = mCp[current]; CtrlPoint ctrlFuture = mCp[current + 1]; float duration0 = ctrlCurrent.mTime - ctrlPast.mTime; float duration1 = ctrlFuture.mTime - ctrlCurrent.mTime; float dot0 = Quaternion.Dot(ctrlCurrent.mVal, ctrlPast.mVal); float dot1 = Quaternion.Dot(ctrlCurrent.mVal, ctrlFuture.mVal); ctrlCurrent.mTan = Interpolation.GetHermiteTangent(dot0, dot1, duration0, duration1); ctrlCurrent.mCtrl = Interpolation.GetSquadControlRotation(ctrlPast.mVal, ctrlCurrent.mVal, ctrlFuture.mVal); } } mIsSmooth = true; }
/// <summary> /// Add a new key to the spline at the specified time /// </summary> public void AddKey(float time, Quaternion rot) { CtrlPoint ctrl = new CtrlPoint(); ctrl.mTime = time; ctrl.mVal = rot; ctrl.mTan = 0.0f; ctrl.mCtrl = rot; mIsSmooth = false; int index = 0; // Find the index where the control point should be added for (int i = mCp.Count; i > 0; ) { CtrlPoint point = mCp[--i]; if (point.mTime < time) { index = i + 1; break; } } // Ensure that the rotation always takes the shortest path if (index > 0 && mCp.Count > 0) { CtrlPoint prev = mCp[index - 1]; if (Quaternion.Dot(prev.mVal, ctrl.mVal) < 0.0f) { ctrl.mVal = new Quaternion(-ctrl.mVal.x, -ctrl.mVal.y, -ctrl.mVal.z, -ctrl.mVal.w); ctrl.mCtrl = ctrl.mVal; } } // Add this control point if (index == mCp.Count) { mCp.Add(ctrl); } else { mLastIndex = 0; mLastSample = 0.0f; mCp.Insert(index, ctrl); } }
/// <summary> /// Add a new key to the spline at the specified time /// </summary> public void AddKey (float time, Vector3 pos) { CtrlPoint ctrl = new CtrlPoint(); ctrl.mTime = time; ctrl.mVal = pos; ctrl.mTan = Vector3.zero; mIsSmooth = false; int index = 0; for (int i = mCp.Count; i > 0; ) { CtrlPoint point = mCp[--i]; if (point.mTime < time) { index = i + 1; break; } } if (index == mCp.Count) { mCp.Add(ctrl); } else { mLastIndex = 0; mLastSample = 0.0f; mCp.Insert(index, ctrl); } }