談談工作中的低層運動控制方法吧。動畫師設計動畫時一般先設計好物體的運動軌迹,然後指定物體沿該軌迹的運動。物體的運動軌迹為樣條曲線,由使用者互動給出。 假設物體的運動軌迹為一空間參數曲線Q(u),我們必須對Q(u)等間隔采樣,以求得物體在每一幀的位置。但是,當對參數u等間隔采樣時,并不能得到樣條曲線上的等間隔采樣,因為等間距的參數不一定對應等間距的弧長。由于弧長函數s=A(u)是u的嚴格增函數,是以s和u是一對一的關系。A(u)是一個積分方程,它沒有解析解。我們無法直接将A -1(s)解析表達出來,通常隻能采用數值求解的方法。此方法在《Advanced Animation and Rendering Techniques》中有詳細說明,此書作者Watt還根據他們的實踐提出了一種基于向前差分的近似計算方法,這在算法中均以實作。而我們的軌迹用什麼樣條的類型來表示呢?計算機輔助幾何設計中常用的樣條函數有Bezier、B樣條、β樣條,各有優缺點吧。 B樣條是動畫中較常用的曲線之一,其二階連續性保證了運動的光滑性,局部性保證了可對動畫進行局部調整,是以非常适合于作軌迹曲線,但并不太适合關鍵幀插值。在Hermite函數基礎上Kochanek将兩個附加參數引入到限制方程中,得到的樣條函數非常适合關鍵幀插值系統。 具體的Hermite樣條函數很多有講解,隻列出入切矢量和出切矢量的一般公式:
張量參數 t用來控制曲線在插值點處的尖銳性;偏移量參數b用來調整源弦和目标弦的相對權值;連續性參數c來控制左右切向的大小。利用這三個參數非常适合于指定曲線的形狀調整。 關于位置插值曲線的設計: class Spline { public: Spline(); virtual ~Spline(); public: void AddKeyPoint(CPoint3D* const pt); void RemovePoint(CPoint3D* const pt); //return the point of the arc length being s(0<= s <=1) virtual CPoint3D ArcLengthPoint(double s) = 0; //The method based on forward difference approximately virtual CPoint3D ArcIntervalLengthPoint(double s) = 0; //Build the segments according to KeyPoints, whose spline type may be Hermite, //Bspline, Bezier inherited from Spline class virtual void BuildSegment() = 0; //Update these KeyPoint values when data are changed virtual void UpdateSplineValues() = 0; protected: public: static vector<CPoint3D*> m_splineKeyPoint; private: Spline(const Spline& s); Spline& operator =(const Spline& s); }; class HermiteSpline : public Spline { public: HermiteSpline(); virtual ~HermiteSpline(); public: void SetLengths(); //build a table of u against accumulated arclength virtual CPoint3D ArcLengthPoint(double s); void SetIntervalLengths(); //a method based on forward differences virtual CPoint3D ArcIntervalLengthPoint(double s); virtual void BuildSegment(); virtual void UpdateSplineValues(); private: class HermiteSegment { public: virtual ~HermiteSegment() {}; HermiteSegment(const CPoint3D* const p0, const CPoint3D* const p1, const CPoint3D* const p2, const CPoint3D* const p3); private: HermiteSegment(); HermiteSegment(const HermiteSegment& segment); HermiteSegment& operator =(const HermiteSegment& segment); public: //tension [-1, 1] default value is 0.0,可控制切矢量Ti的大小 float tension() const { return m_tension; } //bias [-1, 1], default value is 0.0,可控制曲線在Pi處的切向方向 float bias() const { return m_bias; } //continuity [-1, 1], default value is 0.0, 可控制左右切向的大小 float continuity() const { return m_continuity; } //curve resolution, default is 10 int resolution() const { return m_resolution; } void SetTension(float t) { m_tension = t; } void SetBias(float b) { m_bias = b; } void SetContinuity(float c) { m_continuity = c; } void SetResolution(int res) { m_resolution = res; } public: float ArcLength(float ustart, float uend); CPoint3D GetPointOnSegment(float u); private: void SetCoef(); float ArcIntegrand(float u); private: CPoint3D m_keypoint[4]; float m_coef[4][3]; float m_bias; float m_tension; float m_continuity; int m_resolution; bool m_coefIsValid; }; vector<double> m_seglength; //for SetLengths() vector<double> m_intervallength; //for SetIntervalLengths() double m_totallength; int m_deltaU; public: vector<HermiteSegment*> m_curveseg; bool m_segmentsAreValid; bool m_lengthTableAreValid; }; Spline為一抽象類,友善其他插值曲線擴充,例如B樣條等。定義了一個static vector<CPoint3D*> m_splineKeyPoint;為插值曲線類所共有。 關鍵幀插值問題實際上可分為位置插值和朝向插值兩個子問題。對物體朝向的表示我們使用四元數(quaternion)表示。Quaternion的基本概念及應用《Advanced Animation and Rendering Techniques》也有涉及。最重要的概念是機關四元數空間的球面線性插值函數Slerp。從q1到q2的球面線性插值函數如下: CQuaternion CQuaternion::slerp(const CQuaternion& q1, const CQuaternion& q2, const double t, bool allowFlip) 如何用四元數構造物體朝向的插值呢?Shoemake用球面線性插值取代普通的線性插值,将這種幾何構造方法推廣到四維超球面上,進而來構造四維超球面上的三次樣條。 CQuaternion CQuaternion::squad(const CQuaternion& a, const CQuaternion& tgA, const CQuaternion& tgB, const CQuaternion& b, double t) Squad是使用的較普遍的四元數插值得的構造方式。1995年,Kim等人提出了一種構造機關四元數曲線的解析方法。它能把R 3中的曲線推廣到四元數空間,構造出與原始曲線具有類似微分性質的機關四元數曲線。 我在具體實作中使用的是squad方法插值曲線,效果圖如下,圖1定義了4個關鍵幀,圖2定義了6個關鍵幀。
基于文獻[2]中的具有高階導數的機關四元數曲線的一般構造方法以後再實作吧,把四元數函數的導數和角速度搞清楚也不是很難的^_^ See also: 1、《Advanced Animation and Rendering Techniques》 2、Kim M J, Kim M S, Shin S Y. A general construction scheme for unit quaternion curves with simple high order derivatives. Computer Graphics, 1995, 29(3):369-376