主要畫面格系統的實現(Hermite位置插值+Squad四元數空間的朝向插值)

來源:互聯網
上載者:User

    談談工作中的低層運動控制方法吧。動畫師設計動畫時一般先設計好物體的運動軌跡,然後指定物體沿該軌跡的運動。物體的運動軌跡為樣條曲線,由使用者互動給出。    假設物體的運動軌跡為一空間參數曲線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:    /*define the hermite segment between p1 and p2(have two keypoints at least)    construct the segment using four vector (P1, P2, DD1, DS2)    */    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等人提出了一種構造單位四元數曲線的解析方法。它能把R3中的曲線推廣到四元數空間,構造出與原始曲線具有類似微分性質的單位四元數曲線。   我在具體實現中使用的是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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.