123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- #pragma once
- #include <Mathematics/Logger.h>
- #include <Mathematics/ParametricCurve.h>
- namespace WwiseGTE
- {
- template <int N, typename Real>
- class TCBSplineCurve : public ParametricCurve<N, Real>
- {
- public:
-
-
-
-
-
- TCBSplineCurve(int numPoints, Vector<N, Real> const* points,
- Real const* times, Real const* tension, Real const* continuity,
- Real const* bias)
- :
- ParametricCurve<N, Real>(numPoints - 1, times)
- {
- LogAssert(numPoints >= 2 && points != nullptr, "Invalid input.");
- mPoints.resize(numPoints);
- mTension.resize(numPoints);
- mContinuity.resize(numPoints);
- mBias.resize(numPoints);
- std::copy(points, points + numPoints, mPoints.begin());
- std::copy(tension, tension + numPoints, mTension.begin());
- std::copy(continuity, continuity + numPoints, mContinuity.begin());
- std::copy(bias, bias + numPoints, mBias.begin());
- int numSegments = numPoints - 1;
- mA.resize(numSegments);
- mB.resize(numSegments);
- mC.resize(numSegments);
- mD.resize(numSegments);
-
- ComputePoly(0, 0, 1, 2);
- for (int i = 1; i < numSegments - 1; ++i)
- {
- ComputePoly(i - 1, i, i + 1, i + 2);
- }
-
- ComputePoly(numSegments - 2, numSegments - 1, numSegments, numSegments);
- this->mConstructed = true;
- }
- virtual ~TCBSplineCurve()
- {
- }
-
- inline int GetNumPoints() const
- {
- return static_cast<int>(mPoints.size());
- }
- inline Vector<N, Real> const* GetPoints() const
- {
- return &mPoints[0];
- }
- inline Real const* GetTensions() const
- {
- return &mTension[0];
- }
- inline Real const* GetContinuities() const
- {
- return &mContinuity[0];
- }
- inline Real const* GetBiases() const
- {
- return &mBias[0];
- }
-
-
-
-
-
-
-
- virtual void Evaluate(Real t, unsigned int order, Vector<N, Real>* jet) const override
- {
- unsigned int const supOrder = ParametricCurve<N, Real>::SUP_ORDER;
- if (!this->mConstructed || order >= supOrder)
- {
-
- for (unsigned int i = 0; i < supOrder; ++i)
- {
- jet[i].MakeZero();
- }
- return;
- }
- int key;
- Real dt;
- GetKeyInfo(t, key, dt);
- dt /= (this->mTime[key + 1] - this->mTime[key]);
-
- jet[0] = mA[key] + dt * (mB[key] + dt * (mC[key] + dt * mD[key]));
- if (order >= 1)
- {
-
- jet[1] = mB[key] + dt * ((Real)2 * mC[key] + ((Real)3 * dt) * mD[key]);
- if (order >= 2)
- {
-
- jet[2] = (Real)2 * mC[key] + ((Real)6 * dt) * mD[key];
- if (order == 3)
- {
- jet[3] = (Real)6 * mD[key];
- }
- }
- }
- }
- protected:
-
- void ComputePoly(int i0, int i1, int i2, int i3)
- {
- Vector<N, Real> diff = mPoints[i2] - mPoints[i1];
- Real dt = this->mTime[i2] - this->mTime[i1];
-
- Real oneMinusT0 = (Real)1 - mTension[i1];
- Real oneMinusC0 = (Real)1 - mContinuity[i1];
- Real onePlusC0 = (Real)1 + mContinuity[i1];
- Real oneMinusB0 = (Real)1 - mBias[i1];
- Real onePlusB0 = (Real)1 + mBias[i1];
- Real adj0 = (Real)2 * dt / (this->mTime[i2] - this->mTime[i0]);
- Real out0 = (Real)0.5 * adj0 * oneMinusT0 * onePlusC0 * onePlusB0;
- Real out1 = (Real)0.5 * adj0 * oneMinusT0 * oneMinusC0 * oneMinusB0;
-
- Vector<N, Real> tOut = out1 * diff + out0 * (mPoints[i1] - mPoints[i0]);
-
- Real oneMinusT1 = (Real)1 - mTension[i2];
- Real oneMinusC1 = (Real)1 - mContinuity[i2];
- Real onePlusC1 = (Real)1 + mContinuity[i2];
- Real oneMinusB1 = (Real)1 - mBias[i2];
- Real onePlusB1 = (Real)1 + mBias[i2];
- Real adj1 = (Real)2 * dt / (this->mTime[i3] - this->mTime[i1]);
- Real in0 = (Real)0.5 * adj1 * oneMinusT1 * oneMinusC1 * onePlusB1;
- Real in1 = (Real)0.5 * adj1 * oneMinusT1 * onePlusC1 * oneMinusB1;
-
- Vector<N, Real> tIn = in1 * (mPoints[i3] - mPoints[i2]) + in0 * diff;
- mA[i1] = mPoints[i1];
- mB[i1] = tOut;
- mC[i1] = (Real)3 * diff - (Real)2 * tOut - tIn;
- mD[i1] = (Real)-2 * diff + tOut + tIn;
- }
-
- void GetKeyInfo(Real t, int& key, Real& dt) const
- {
- int numSegments = static_cast<int>(mA.size());
- if (t <= this->mTime[0])
- {
- key = 0;
- dt = (Real)0;
- return;
- }
- if (t < this->mTime[numSegments])
- {
- for (int i = 0; i < numSegments; ++i)
- {
- if (t < this->mTime[i + 1])
- {
- key = i;
- dt = t - this->mTime[i];
- return;
- }
- }
- }
- key = numSegments - 1;
- dt = this->mTime[numSegments] - this->mTime[numSegments - 1];
- }
- std::vector<Vector<N, Real>> mPoints;
- std::vector<Real> mTension, mContinuity, mBias;
-
-
-
- std::vector<Vector<N, Real>> mA, mB, mC, mD;
- };
- }
|