Changeset 452 for cafu/trunk

Show
Ignore:
Timestamp:
12/31/11 17:57:20 (5 months ago)
Author:
Carsten
Message:

Model code:
Added the basics of "anim expressions".
Anim expressions define "arithmetic on animation sequences", and are the basis for implementing animation blending and animation channels as described at <http://www.cafu.de/forum/viewtopic.php?f=14&t=925>.

This change adds the expression base class AnimExpressionT and the first concrete class AnimExprStandardT that implements the existing functionality of plain normal animation sequence playback.
The AnimPoseT has been updated to use the new AnimExprStandardT class instead of the previous hard-coded functionality.

The next revisions will provide additional implementations for AnimExpressionT that implement blending and channel filtering.

Location:
cafu/trunk/Libs
Files:
2 added
4 modified

Legend:

Unmodified
Added
Removed
  • cafu/trunk/Libs/Models/AnimPose.cpp

    r438 r452  
    2121 
    2222#include "AnimPose.hpp" 
     23#include "AnimExpr.hpp" 
    2324#include "Model_cmdl.hpp" 
    2425 
     
    3132AnimPoseT::AnimPoseT(const CafuModelT& Model, int SequNr, float FrameNr) 
    3233    : m_Model(Model), 
    33       m_SequNr(SequNr), 
    34       m_FrameNr(FrameNr), 
     34      m_AnimExpr(NULL), 
    3535      m_SuperPose(NULL), 
    3636      m_DlodPose(m_Model.GetDlodModel() ? new AnimPoseT(*m_Model.GetDlodModel(), SequNr, FrameNr) : NULL),  // Recursively create the chain of dlod poses matching the chain of dlod models. 
    37       m_NeedsRecache(true), 
     37      m_RecacheCount(0), 
    3838      m_BoundingBox() 
    3939{ 
    40     NormalizeInput(); 
     40    m_AnimExpr=new AnimExprStandardT(m_Model, SequNr, FrameNr); 
    4141} 
    4242 
     
    4545{ 
    4646    delete m_DlodPose; 
     47    delete m_AnimExpr; 
    4748} 
    4849 
     
    120121    typedef CafuModelT::JointT JointT; 
    121122    typedef CafuModelT::MeshT  MeshT; 
    122     typedef CafuModelT::AnimT  AnimT; 
    123123 
    124124    const ArrayT<JointT>& Joints=m_Model.GetJoints(); 
    125125    const ArrayT<MeshT>&  Meshes=m_Model.GetMeshes(); 
    126     const ArrayT<AnimT>&  Anims =m_Model.GetAnims(); 
    127126 
    128127 
     
    132131    // ************************************************************************************************************** 
    133132 
    134     if (m_SequNr==-1) 
    135     { 
    136         // Don't animate, just use the bind pose defined in the model file. 
    137         for (unsigned long JointNr=0; JointNr<Joints.Size(); JointNr++) 
    138         { 
    139             if (m_SuperPose) 
    140             { 
    141                 const MatrixT* SuperMat=m_SuperPose->GetJointMatrix(Joints[JointNr].Name); 
    142  
    143                 if (SuperMat) 
    144                 { 
    145                     m_JointMatrices[JointNr]=*SuperMat; 
    146                     continue; 
    147                 } 
    148             } 
    149  
    150             const JointT& J=Joints[JointNr]; 
    151             const MatrixT RelMatrix(J.Pos, cf::math::QuaternionfT::FromXYZ(J.Qtr), J.Scale); 
    152  
    153             m_JointMatrices[JointNr]=(J.Parent==-1) ? RelMatrix : m_JointMatrices[J.Parent]*RelMatrix; 
    154         } 
    155     } 
    156     else 
    157     { 
    158         // m_SequNr is a valid index into Anims, so use that. 
    159         const AnimT& Anim=Anims[m_SequNr]; 
    160         const int    Frame_0=int(m_FrameNr);                                        // If m_FrameNr == 17.83, then Frame_0 == 17 
    161         const float  Frame_f=m_FrameNr-Frame_0;                                     //                             Frame_f ==  0.83 
    162         const int    Frame_1=(Frame_0+1>=int(Anim.Frames.Size())) ? 0 : Frame_0+1;  //                             Frame_1 == 18 
    163  
    164         for (unsigned long JointNr=0; JointNr<Joints.Size(); JointNr++) 
    165         { 
    166             if (m_SuperPose) 
    167             { 
    168                 const MatrixT* SuperMat=m_SuperPose->GetJointMatrix(Joints[JointNr].Name); 
    169  
    170                 if (SuperMat) 
    171                 { 
    172                     m_JointMatrices[JointNr]=*SuperMat; 
    173                     continue; 
    174                 } 
    175             } 
    176  
    177             const AnimT::AnimJointT& AJ=Anim.AnimJoints[JointNr]; 
    178  
    179             Vector3fT Data_0[3]={ AJ.DefaultPos, AJ.DefaultQtr, AJ.DefaultScale }; 
    180             Vector3fT Data_1[3]={ AJ.DefaultPos, AJ.DefaultQtr, AJ.DefaultScale }; 
    181  
    182             // Determine the position, quaternion and scale for Frame_0 and Frame_1. 
    183             unsigned int FlagCount=0; 
    184  
    185             for (int i=0; i<9; i++) 
    186             { 
    187                 if ((AJ.Flags >> i) & 1) 
    188                 { 
    189                     Data_0[i/3][i % 3]=Anim.Frames[Frame_0].AnimData[AJ.FirstDataIdx+FlagCount]; 
    190                     Data_1[i/3][i % 3]=Anim.Frames[Frame_1].AnimData[AJ.FirstDataIdx+FlagCount]; 
    191  
    192                     FlagCount++; 
    193                 } 
    194             } 
    195  
    196             // Interpolate the position and quaternion according to the fraction Frame_f. 
    197             const Vector3fT              Pos  =Data_0[0]*(1.0f-Frame_f) + Data_1[0]*Frame_f; 
    198             const cf::math::QuaternionfT Quat =slerp(cf::math::QuaternionfT::FromXYZ(Data_0[1]), cf::math::QuaternionfT::FromXYZ(Data_1[1]), Frame_f); 
    199             const Vector3fT              Scale=Data_0[2]*(1.0f-Frame_f) + Data_1[2]*Frame_f; 
    200  
    201             // Compute the matrix that is relative to the parent bone, and finally obtain the absolute matrix for that bone! 
    202             const MatrixT RelMatrix(Pos, Quat, Scale); 
    203             const JointT& J=Joints[JointNr]; 
    204  
    205             m_JointMatrices[JointNr]=(J.Parent==-1) ? RelMatrix : m_JointMatrices[J.Parent]*RelMatrix; 
    206         } 
     133    for (unsigned long JointNr=0; JointNr<Joints.Size(); JointNr++) 
     134    { 
     135        if (m_SuperPose) 
     136        { 
     137            const MatrixT* SuperMat=m_SuperPose->GetJointMatrix(Joints[JointNr].Name); 
     138 
     139            if (SuperMat) 
     140            { 
     141                m_JointMatrices[JointNr]=*SuperMat; 
     142                continue; 
     143            } 
     144        } 
     145 
     146        float                  Weight; 
     147        Vector3fT              Pos; 
     148        cf::math::QuaternionfT Quat; 
     149        Vector3fT              Scale; 
     150 
     151        m_AnimExpr->GetData(JointNr, Weight, Pos, Quat, Scale); 
     152 
     153        // Compute the matrix that is relative to the parent bone, and finally obtain the absolute matrix for that bone! 
     154        const MatrixT RelMatrix(Pos, Quat, Scale); 
     155        const JointT& J=Joints[JointNr]; 
     156 
     157        // assert(Weight==1.0f); 
     158        m_JointMatrices[JointNr]=(J.Parent==-1) ? RelMatrix : m_JointMatrices[J.Parent]*RelMatrix; 
    207159    } 
    208160 
     
    261213    if (m_Model.GetUseGivenTS()) 
    262214    { 
    263         assert(Anims.Size()==0);  // It doesn't make sense to have statically given tangent-space axes with *animated* geometry... 
     215        assert(m_Model.GetAnims().Size()==0);  // It doesn't make sense to have statically given tangent-space axes with *animated* geometry... 
    264216 
    265217        // Copy the given tangent space details into the pose. 
     
    447399void AnimPoseT::Recache() const 
    448400{ 
    449     if (!m_NeedsRecache && !m_SuperPose) return; 
     401    if (!m_SuperPose && m_RecacheCount==m_AnimExpr->GetChangeCount()) return; 
    450402 
    451403    SyncDimensions(); 
     
    462414    //     y(); 
    463415 
    464     m_NeedsRecache=false; 
    465 } 
    466  
    467  
    468 void AnimPoseT::NormalizeInput() 
    469 { 
    470     const ArrayT<CafuModelT::AnimT>& Anims=m_Model.GetAnims(); 
    471  
    472     // m_SequNr==-1 means "use the bind pose from the model file only (no anim)". 
    473     if (m_SequNr < -1) m_SequNr = -1; 
    474     if (m_SequNr >= int(Anims.Size())) m_SequNr = -1; 
    475     if (m_SequNr != -1 && (Anims[m_SequNr].FPS<0.0 || Anims[m_SequNr].Frames.Size()==0)) m_SequNr = -1; 
    476  
    477     m_FrameNr=std::max(m_FrameNr, 0.0f); 
    478     m_FrameNr=(m_SequNr==-1) ? 0.0f : fmod(m_FrameNr, float(Anims[m_SequNr].Frames.Size())); 
    479 } 
     416    m_RecacheCount=m_AnimExpr->GetChangeCount(); 
     417} 
     418 
     419 
     420int   AnimPoseT::GetSequNr() const { return dynamic_cast<AnimExprStandardT*>(m_AnimExpr)->GetSequNr(); } 
     421float AnimPoseT::GetFrameNr() const { return dynamic_cast<AnimExprStandardT*>(m_AnimExpr)->GetFrameNr(); } 
    480422 
    481423 
    482424void AnimPoseT::SetSequNr(int SequNr) 
    483425{ 
    484     if (m_SequNr==SequNr) return; 
    485  
    486     m_SequNr=SequNr; 
    487     NormalizeInput(); 
    488  
    489     m_NeedsRecache=true; 
     426    dynamic_cast<AnimExprStandardT*>(m_AnimExpr)->SetSequNr(SequNr); 
    490427 
    491428    // Recursively update the chain of dlod poses. 
     
    496433void AnimPoseT::SetFrameNr(float FrameNr) 
    497434{ 
    498     if (m_FrameNr==FrameNr) return; 
    499  
    500     m_FrameNr=FrameNr; 
    501     NormalizeInput(); 
    502  
    503     m_NeedsRecache=true; 
     435    dynamic_cast<AnimExprStandardT*>(m_AnimExpr)->SetFrameNr(FrameNr); 
    504436 
    505437    // Recursively update the chain of dlod poses. 
     
    513445 
    514446    m_SuperPose=SuperPose; 
    515  
    516     m_NeedsRecache=true; 
     447    m_RecacheCount=0; 
    517448 
    518449    // Recursively update the chain of dlod poses. 
     
    523454void AnimPoseT::Advance(float Time, bool ForceLoop) 
    524455{ 
    525     // TODO: Beachte korrekte Wrap-Regeln für mit loopen und ohne. 
    526     // TODO: Loops (next vs. ForceLoop) richtig behandeln 
    527     const ArrayT<CafuModelT::AnimT>& Anims=m_Model.GetAnims(); 
    528  
    529     if (m_SequNr<0 || m_SequNr>=int(Anims.Size())) { SetFrameNr(0.0f); return; } 
    530     if (Anims[m_SequNr].Frames.Size()<=1) { SetFrameNr(0.0f); return; } 
    531  
    532     const float NumFrames=float(Anims[m_SequNr].Frames.Size()); 
    533  
    534     float FrameNr=m_FrameNr + Time*Anims[m_SequNr].FPS; 
    535  
    536     if (ForceLoop) 
    537     { 
    538         // Wrap the sequence (it's a looping (repeating) sequence, like idle, walk, ...). 
    539         FrameNr=fmod(FrameNr, NumFrames); 
    540         if (FrameNr<0.0f) FrameNr+=NumFrames; 
    541     } 
    542     else 
    543     { 
    544         // Clamp the sequence (it's a play-once (non-repeating) sequence, like dying). 
    545         // On clamping, stop the sequence 1/100th sec before the end of the last frame. 
    546         if (FrameNr>=NumFrames-1.0f) FrameNr=NumFrames-1.0f-0.01f; 
    547         if (FrameNr<0.0f) FrameNr=0.0f; 
    548     } 
    549  
    550     SetFrameNr(FrameNr); 
     456    m_AnimExpr->AdvanceTime(Time, ForceLoop); 
    551457 
    552458    // Recursively update the chain of dlod poses. 
  • cafu/trunk/Libs/Models/AnimPose.hpp

    r438 r452  
    2929 
    3030 
     31class AnimExpressionT; 
    3132class CafuModelT; 
    3233class MaterialT; 
     
    9394    ~AnimPoseT(); 
    9495 
    95     int GetSequNr() const { return m_SequNr; } 
     96    int GetSequNr() const; 
    9697 
    9798    /// @param SequNr   The number of the animation sequence to use, -1 for the bind pose. 
    9899    void SetSequNr(int SequNr); 
    99100 
    100     float GetFrameNr() const { return m_FrameNr; } 
     101    float GetFrameNr() const; 
    101102 
    102103    /// @param FrameNr      The frame number in the animation sequence to render the model at. 
     
    117118 
    118119    /// Call this if something in the related model has changed. 
    119     void SetNeedsRecache() { m_NeedsRecache=true; } 
     120    void SetNeedsRecache() { m_RecacheCount=0; }    // 0 is different from any value that m_AnimExpr->GetChangedCount() returns. 
    120121 
    121122    /// This method renders the model in this pose. 
     
    170171    void UpdateData() const; 
    171172    void Recache() const; 
    172     void NormalizeInput(); 
    173173 
    174174    const CafuModelT&             m_Model;          ///< The related model that this is a pose for. 
    175     int                           m_SequNr;         ///< The animation sequence number at which we have computed the cache data. 
    176     float                         m_FrameNr;        ///< The animation frame    number at which we have computed the cache data. 
     175    AnimExpressionT*              m_AnimExpr;       ///< The expression that describes the animation state of the joints for which we have computed the cache data. 
    177176    const AnimPoseT*              m_SuperPose; 
    178177    AnimPoseT*                    m_DlodPose;       ///< The next pose in the chain of dlod poses matching the chain of dlod models. 
     
    180179 // bool                          m_DoCache;        ///< Cache the computed data? (Set to true by the user if he want to re-use this instance.) 
    181180 
    182     mutable bool                  m_NeedsRecache;   ///< wird auf 'true' gesetzt wann immer SetSequ(), SetFrameNr() oder AdvanceAll() o.ä. aufgerufen wird, übernimmt m_Draw_CachedDataAt*Nr Funktionalität. 
     181    mutable unsigned int          m_RecacheCount;   ///< Used to detect if the m_AnimExpr has changed, so that our matrices, meshes etc. can be recached. 
    183182    mutable ArrayT<MatrixT>       m_JointMatrices;  ///< The transformation matrices that represent the pose of the skeleton at the given animation sequence and frame number. 
    184183    mutable ArrayT<MeshInfoT>     m_MeshInfos;      ///< Additional data for each mesh in m_Model. 
  • cafu/trunk/Libs/SConscript

    r428 r452  
    1414                    MapFile.cpp 
    1515                    Models/Loader.cpp Models/Loader_ase.cpp Models/Loader_cmdl.cpp Models/Loader_dlod.cpp Models/Loader_dummy.cpp Models/Loader_lwo.cpp Models/Loader_md5.cpp 
    16                     Models/Loader_mdl.cpp Models/AnimPose.cpp 
     16                    Models/Loader_mdl.cpp Models/AnimExpr.cpp Models/AnimPose.cpp 
    1717                    Models/Model_cmdl.cpp Models/ModelManager.cpp 
    1818                    Network/Network.cpp ParticleEngine/ParticleEngineMS.cpp PlatformAux.cpp Terrain/Terrain.cpp