OGRE的Animation相关类


 

KeyFrame

KeyFrame是基类,有四个子类,NumericKeyFrame,TransformKeyFrame,VertexMorphKeyFrame,

VertexPoseKeyFrame.

KeyFrame:关键帧,基类

class_OgreExportKeyFrame : publicAnimationAlloc

    {

    public:

        KeyFrame(constAnimationTrack* parent, Realtime);

        构造函数由AnimationTrack调用

        virtual ~KeyFrame() {}          

        获得关键帧在动画序列里的时间

        Real getTime(void) const { return mTime; }

        复制关键帧的函数,因为是virtual,每个子类都有各自的复制函数

        virtualKeyFrame* _clone(AnimationTrack* newParent) const;

    protected:

        Real mTime;                                        储存该关键帧在动画序列的时间

        constAnimationTrack* mParentTrack;                父亲Track

};

 

NumericKeyFrame:数值关键帧,储存数值

class_OgreExportNumericKeyFrame : publicKeyFrame

    {

    public:

         NumericKeyFrame(constAnimationTrack* parent, Realtime);

        ~NumericKeyFrame() {}

 

        获得关键帧存的任何值

        virtualconstAnyNumeric& getValue(void) const;

        设置值

        virtualvoid setValue(constAnyNumeric& val);

NumericKeyFrame的复制函数

                KeyFrame* _clone(AnimationTrack* newParent) const;

    protected:

        AnyNumeric mValue;

};

 

TransformKeyFrame:变换关键帧,储存了各种变换,包括平移,旋转,缩放

class_OgreExportTransformKeyFrame : publicKeyFrame

    {

    public:

               TransformKeyFrame(constAnimationTrack* parent, Realtime);

        ~TransformKeyFrame() {}

     设置这个帧中动画物体的平移

        virtualvoid setTranslate(constVector3& trans);

 

               constVector3& getTranslate(void) const;

 

       设置这个帧中动画物体的缩放

        virtualvoid setScale(constVector3& scale);

        virtualconstVector3& getScale(void) const;

     设置这个帧中动画物体的旋转,用四元数来旋转

        virtualvoid setRotation(constQuaternion& rot);

        virtualconstQuaternion& getRotation(void) const;

 

        复制函数

        KeyFrame* _clone(AnimationTrack* newParent) const;

    protected:

        Vector3 mTranslate;

        Vector3 mScale;

        Quaternion mRotate;

 

 

    };

VertexMorphKeyFrame:顶点Morph关键帧

储存在缓存中的顶点位置,是为了和其他在同一个track的关键帧做内插值

class_OgreExportVertexMorphKeyFrame : publicKeyFrame

    {

    public:

         VertexMorphKeyFrame(constAnimationTrack* parent, Realtime);

        ~VertexMorphKeyFrame() {}

       用在缓存中的前三个float元素来当作关键帧中的位置

        void setVertexBuffer(constHardwareVertexBufferSharedPtr& buf);

constHardwareVertexBufferSharedPtr& getVertexBuffer(void) const;

        复制函数

        KeyFrame* _clone(AnimationTrack* newParent) const;     

 

    protected:

        HardwareVertexBufferSharedPtr mBuffer;

 

    };

VertexPoseKeyFrame:动作点关键帧

该关键帧参考了Mesh::Pose以一个确定的影响程度

class_OgreExportVertexPoseKeyFrame : publicKeyFrame

    {

    public:

         VertexPoseKeyFrame(constAnimationTrack* parent, Realtime);

        ~VertexPoseKeyFrame() {}

 

      

        structPoseRef    动作参考

        {

            typedef unsigned short ushort)Mesh包含所有pose的所有顶点信息在一个list

            这个poseIndex存的就是参考poseMesh里的list的索引

            ushort poseIndex;

            Real influence;      影响程度在0.0-1.0

 

            PoseRef(ushortp, Reali) : poseIndex(p), influence(i) {}

        };

        typedefvector<PoseRef>::typePoseRefList;

 

        下面4个函数都是对PoseRef参考动作的操作

        void addPoseReference(ushortposeIndex, Realinfluence);

        void updatePoseReference(ushortposeIndex, Realinfluence);

        void removePoseReference(ushortposeIndex);

         void removeAllPoseReferences(void);

 

        mPoseRefs(就是存了PoseReflist)的操作

        constPoseRefList& getPoseReferences(void) const;

        typedefVectorIterator<PoseRefList> PoseRefIterator;

        typedefConstVectorIterator<PoseRefList> ConstPoseRefIterator;

        PoseRefIterator getPoseReferenceIterator(void);

        ConstPoseRefIterator getPoseReferenceIterator(void) const;

       

KeyFrame* _clone(AnimationTrack* newParent) const;

        void _applyBaseKeyFrame(constVertexPoseKeyFrame* base);

       

    protected:

        PoseRefList mPoseRefs;

 

    };

下面是对mPoseRefs操作的具体代码,可以看出就是许多对list的操作

voidVertexPoseKeyFrame::addPoseReference(ushortposeIndex, Realinfluence)

    {

        mPoseRefs.push_back(PoseRef(poseIndex, influence));

    }

    //---------------------------------------------------------------------

    voidVertexPoseKeyFrame::updatePoseReference(ushortposeIndex, Realinfluence)

    {

        for (PoseRefList::iterator i = mPoseRefs.begin(); i != mPoseRefs.end(); ++i)

        {

            if (i->poseIndex == poseIndex)

            {

                i->influence = influence;

                return;

            }

        }

        // if we got here, we didn't find it

        addPoseReference(poseIndex, influence);

 

    }

    //---------------------------------------------------------------------

    voidVertexPoseKeyFrame::removePoseReference(ushortposeIndex)

    {

        for (PoseRefList::iterator i = mPoseRefs.begin(); i != mPoseRefs.end(); ++i)

        {

            if (i->poseIndex == poseIndex)

            {

                mPoseRefs.erase(i);

                return;

            }

        }

    }

    //---------------------------------------------------------------------

    voidVertexPoseKeyFrame::removeAllPoseReferences(void)

    {

        mPoseRefs.clear();

}

 

 

AnimationTrack(动画轨迹)

动画轨迹由多个关键帧组成,负责做两个关键帧之间的插值运算。

同样是一个基类,有3个子类,NodeAnimationTrack,NumericAnimationTrack,VertexAnimationTrack. 一个track实际上就是一系列Keyframes影响一个动画物体。

Since the most common animable object is a Node, there are options in this class for associating the track with a Node which will receive keyframe updates automatically when the 'apply' method is called.

 

TimeIndex通常用于寻找keyframe

class_OgreExportTimeIndex

    {

    protected:

        Real mTimePos;

        uint mKeyIndex;

        staticconstuint INVALID_KEY_INDEX = (uint)-1;

    public:

     

        TimeIndex(RealtimePos)

            : mTimePos(timePos)

            , mKeyIndex(INVALID_KEY_INDEX)

        {

        }

        TimeIndex(RealtimePos, uintkeyIndex)

            : mTimePos(timePos)

            , mKeyIndex(keyIndex)

        {

        }

        bool hasKeyIndex(void) const

        {

            return mKeyIndex != INVALID_KEY_INDEX;

        }

        Real getTimePos(void) const

        {

            return mTimePos;

        }

        uint getKeyIndex(void) const

        {

            return mKeyIndex;

        }

};

 

AniamtionTrack代码主要函数

class_OgreExportAnimationTrack : publicAnimationAlloc

    {

    public:

 

        Listener允许你重写一个确定的AniamtionTrack

        class_OgreExportListener

        {

        public:

            virtual ~Listener() {}

            virtualbool getInterpolatedKeyFrame(constAnimationTrack* t, constTimeIndex& timeIndex, KeyFrame* kf) = 0;

        };

        AnimationTrack(Animation* parent, unsignedshorthandle);

        virtual ~AnimationTrack();

        unsignedshort getHandle(void) const { return mHandle; }

        virtualunsignedshort getNumKeyFrames(void) const;

        virtualKeyFrame* getKeyFrame(unsignedshortindex) const;

        返回一个值,介于0-1,如果值为0则代表keyFrame1,如果值为0.25,则为keyFrame1和keyFrame2的四分之一处。timeIndex是用于两帧之间时间标记,keyFrame1和KeyFrame2分别是用来构造新帧的帧模板,最后一个参数指向了形成的帧

        virtualReal getKeyFramesAtTime(constTimeIndex& timeIndex, KeyFrame** keyFrame1, KeyFrame** keyFrame2,

            unsignedshort* firstKeyIndex = 0) const;

       创造一个KeyFrame,在指定的timePos,创建最好按时间顺序

        virtualKeyFrame* createKeyFrame(RealtimePos);

       获得指定的插值帧

        virtualvoid getInterpolatedKeyFrame(constTimeIndex& timeIndex, KeyFrame* kf) const = 0;

 

       在指定的timeIndex的目标运用该AnimationTrack

        virtualvoid apply(constTimeIndex& timeIndex, Realweight = 1.0, Realscale = 1.0f) = 0;

    

NumericAnimationTrack 数值动作轨迹,用来处理一般的动作数值, 由NumeraicKeyFrame来构成

class_OgreExportNumericAnimationTrack : publicAnimationTrack

    {

    public:

        /// Constructor

        NumericAnimationTrack(Animation* parent, unsignedshorthandle);

        /// Constructor, associates with an AnimableValue

        NumericAnimationTrack(Animation* parent, unsignedshorthandle,

            AnimableValuePtr& target);

        virtualNumericKeyFrame* createNumericKeyFrame(RealtimePos);

        virtualvoid getInterpolatedKeyFrame(constTimeIndex& timeIndex, KeyFrame* kf) const;

        virtualvoid apply(constTimeIndex& timeIndex, Realweight = 1.0, Realscale = 1.0f);

        运用一个animation track到一个给定的Animation

        void applyToAnimable(constAnimableValuePtr& anim, constTimeIndex& timeIndex,

            Realweight = 1.0, Realscale = 1.0f);

        virtualconstAnimableValuePtr& getAssociatedAnimable(void) const;

        virtualvoid setAssociatedAnimable(constAnimableValuePtr& val);

        NumericKeyFrame* getNumericKeyFrame(unsignedshortindex) const;

        NumericAnimationTrack* _clone(Animation* newParent) const;

    protected:

       

        AnimableValuePtr mTargetAnim;

        KeyFrame* createKeyFrameImpl(Realtime);

};

最重要的是getInterpolatedKeyFrameapplyToAnimable

voidNumericAnimationTrack::getInterpolatedKeyFrame(constTimeIndex& timeIndex,

        KeyFrame* kf) const

    {

        if (mListener)

        {

            if (mListener->getInterpolatedKeyFrame(this, timeIndex, kf))

                return;

        }

 

        NumericKeyFrame* kret = static_cast<NumericKeyFrame*>(kf);

 

        // Keyframe pointers

        KeyFrame *kBase1, *kBase2;

        NumericKeyFrame *k1, *k2;

        unsignedshort firstKeyIndex;

 

        Real t = this->getKeyFramesAtTime(timeIndex, &kBase1, &kBase2, &firstKeyIndex);

        k1 = static_cast<NumericKeyFrame*>(kBase1);

        k2 = static_cast<NumericKeyFrame*>(kBase2);

 

        if (t == 0.0)

        {

            // Just use k1

            kret->setValue(k1->getValue());

        }

        else

        {

            // Interpolate by t

            AnyNumeric diff = k2->getValue() - k1->getValue();

            kret->setValue(k1->getValue() + diff * t);

        }

}

voidNumericAnimationTrack::applyToAnimable(constAnimableValuePtr& anim, constTimeIndex& timeIndex,

        Realweight, Realscale)

    {

        // Nothing to do if no keyframes or zero weight, scale

        if (mKeyFrames.empty() || !weight || !scale)

            return;

 

        NumericKeyFrame kf(0, timeIndex.getTimePos());

        getInterpolatedKeyFrame(timeIndex, &kf);

        // add to existing. Weights are not relative, but treated as

        // absolute multipliers for the animation

        AnyNumeric val = kf.getValue() * (weight * scale);

 

        anim->applyDeltaValue(val);

 

    }

 

 

 

NodeAnimationTrack 节点动作轨迹,用来处理节点的动画变换, 由TransformKeyFrame来构成

 

class_OgreExport NodeAnimationTrack : public AnimationTrack

    { //---------------------结点动作轨迹

    public:

        /// Constructor

        NodeAnimationTrack(Animation* parent, unsigned short handle);

        /// Constructor, associates with a Node

        NodeAnimationTrack(Animation* parent, unsigned short handle,

            Node* targetNode);

        /// Destructor

        virtual ~NodeAnimationTrack();

        virtual TransformKeyFrame* createNodeKeyFrame(Real timePos);

        virtual void setAssociatedNode(Node* node);

        运动到节点上

virtual void applyToNode(Node* node, const TimeIndex& timeIndex, Real weight = 1.0,

            Real scale = 1.0f);

        virtual void setUseShortestRotationPath(bool useShortestPath);

        virtual bool getUseShortestRotationPath() const;

        virtual void getInterpolatedKeyFrame(const TimeIndex& timeIndex, KeyFrame* kf) const;

 

        virtual void apply(const TimeIndex& timeIndex, Real weight = 1.0, Real scale = 1.0f);

        void _keyFrameDataChanged(voidconst;

        virtual TransformKeyFrame* getNodeKeyFrame(unsigned short index) const;

        virtual bool hasNonZeroKeyFrames(voidconst;

        virtual void optimise(void);

        NodeAnimationTrack* _clone(Animation* newParent) const;

    protected:

        KeyFrame* createKeyFrameImpl(Real time);

virtual void buildInterpolationSplines(voidconst;

 

        struct Splines  //里面保存了修改器

        {

            SimpleSpline positionSpline;

            SimpleSpline scaleSpline;

            RotationalSpline rotationSpline;

        };

 

        Node* mTargetNode;

        mutable Splines* mSplines;

        mutable bool mSplineBuildNeeded;

        mutable bool mUseShortestRotationPath ;

    };

 

 

其中重要的是

voidNodeAnimationTrack::applyToNode(Node* node, constTimeIndex& timeIndex, Realweight,

        Realscl)

    {

        // Nothing to do if no keyframes or zero weight or no node

        if (mKeyFrames.empty() || !weight || !node)

             return;

 

        TransformKeyFrame kf(0, timeIndex.getTimePos());

        getInterpolatedKeyFrame(timeIndex, &kf);

 

        // add to existing. Weights are not relative, but treated as absolute multipliers for the animation

        Vector3 translate = kf.getTranslate() *weight*scl;

        node->translate(translate);

 

        // interpolate between no-rotation and full rotation, to point 'weight', so 0 = no rotate, 1 = full

        Quaternion rotate;

        Animation::RotationInterpolationMode rim =

             mParent->getRotationInterpolationMode();

        if (rim == Animation::RIM_LINEAR)

        {

             rotate =Quaternion::nlerp(weight, Quaternion::IDENTITY, kf.getRotation(), mUseShortestRotationPath);

        }

        else//if (rim == Animation::RIM_SPHERICAL)

        {

             rotate =Quaternion::Slerp(weight, Quaternion::IDENTITY, kf.getRotation(), mUseShortestRotationPath);

        }

        node->rotate(rotate);

 

        Vector3 scale = kf.getScale();

        // Not sure how to modify scale for cumulative anims... leave it alone

        //scale = ((Vector3::UNIT_SCALE - kf.getScale()) * weight) + Vector3::UNIT_SCALE;

        if (scale !=Vector3::UNIT_SCALE)

        {

             if (scl != 1.0f)

                 scale =Vector3::UNIT_SCALE + (scale -Vector3::UNIT_SCALE) *scl;

             elseif (weight != 1.0f)

                 scale =Vector3::UNIT_SCALE + (scale -Vector3::UNIT_SCALE) *weight;

        }

        node->scale(scale);

 

    }

 

VertexAnimationTrack 顶点动作轨迹,用来处理顶点的位置变化, 由VertexMorphKeyFrame和VertexPoseKeyFrame来构成

class_OgreExportVertexAnimationTrack : publicAnimationTrack

    {

    public:

        /** The target animation mode */

        enumTargetMode

        {

            /// Interpolate vertex positions in software

            TM_SOFTWARE,

            /** Bind keyframe 1 to position, and keyframe 2 to a texture coordinate

                for interpolation in hardware */

            TM_HARDWARE

        };

   

        VertexAnimationTrack(Animation* parent, unsignedshorthandle, VertexAnimationTypeanimType);

        VertexAnimationTrack(Animation* parent, unsignedshorthandle, VertexAnimationTypeanimType,

            VertexData* targetData, TargetModetarget = TM_SOFTWARE);

        VertexAnimationType getAnimationType(void) const { return mAnimationType; }

        bool getVertexAnimationIncludesNormals() const;

        virtualVertexMorphKeyFrame* createVertexMorphKeyFrame(RealtimePos);

        virtualVertexPoseKeyFrame* createVertexPoseKeyFrame(RealtimePos);

        virtualvoid getInterpolatedKeyFrame(constTimeIndex& timeIndex, KeyFrame* kf) const;

        virtualvoid apply(constTimeIndex& timeIndex, Realweight = 1.0, Realscale = 1.0f);

        virtualvoid applyToVertexData(VertexData* data,

            constTimeIndex& timeIndex, Realweight = 1.0,

            constPoseList* poseList = 0);

        void _applyBaseKeyFrame(constKeyFrame* base);

    protected:

        VertexAnimationType mAnimationType;

        VertexData* mTargetVertexData;

        TargetMode mTargetMode;

        KeyFrame* createKeyFrameImpl(Realtime);

        void applyPoseToVertexData(constPose* pose, VertexData* data, Realinfluence);

};

 

其中重要的还是applyToVertexData

voidVertexAnimationTrack::applyToVertexData(VertexData* data,

        constTimeIndex& timeIndex, Realweight, constPoseList* poseList)

    {

        // Nothing to do if no keyframes or no vertex data

        if (mKeyFrames.empty() || !data)

            return;

 

        // Get keyframes

        KeyFrame *kf1, *kf2;

        Real t = getKeyFramesAtTime(timeIndex, &kf1, &kf2);

 

        if (mAnimationType == VAT_MORPH)

        {

            VertexMorphKeyFrame* vkf1 = static_cast<VertexMorphKeyFrame*>(kf1);

            VertexMorphKeyFrame* vkf2 = static_cast<VertexMorphKeyFrame*>(kf2);

 

            if (mTargetMode == TM_HARDWARE)

            {

                // If target mode is hardware, need to bind our 2 keyframe buffers,

                // one to main pos, one to morph target texcoord

                assert(!data->hwAnimationDataList.empty() &&

                    "Haven't set up hardware vertex animation elements!");

 

                // no use for TempBlendedBufferInfo here btw

                // NB we assume that position buffer is unshared, except for normals

                // VertexDeclaration::getAutoOrganisedDeclaration should see to that

                constVertexElement* posElem =

                    data->vertexDeclaration->findElementBySemantic(VES_POSITION);

                // Set keyframe1 data as original position

                data->vertexBufferBinding->setBinding(

                    posElem->getSource(), vkf1->getVertexBuffer());

                // Set keyframe2 data as derived

                data->vertexBufferBinding->setBinding(

                    data->hwAnimationDataList[0].targetBufferIndex,

                    vkf2->getVertexBuffer());

                // save T for use later

                data->hwAnimationDataList[0].parametric = t;

 

            }

            else

            {

                // If target mode is software, need to software interpolate each vertex

 

                Mesh::softwareVertexMorph(

                    t, vkf1->getVertexBuffer(), vkf2->getVertexBuffer(), data);

            }

        }

        else

        {

            // Pose

 

            VertexPoseKeyFrame* vkf1 = static_cast<VertexPoseKeyFrame*>(kf1);

            VertexPoseKeyFrame* vkf2 = static_cast<VertexPoseKeyFrame*>(kf2);

            constVertexPoseKeyFrame::PoseRefList& poseList1 = vkf1->getPoseReferences();

            constVertexPoseKeyFrame::PoseRefList& poseList2 = vkf2->getPoseReferences();

            for (VertexPoseKeyFrame::PoseRefList::const_iterator p1 = poseList1.begin();

                p1 != poseList1.end(); ++p1)

            {

                Real startInfluence = p1->influence;

                Real endInfluence = 0;

                // Search for entry in keyframe 2 list (if not there, will be 0)

                for (VertexPoseKeyFrame::PoseRefList::const_iterator p2 = poseList2.begin();

                    p2 != poseList2.end(); ++p2)

                {

                    if (p1->poseIndex == p2->poseIndex)

                    {

                        endInfluence = p2->influence;

                        break;

                    }

                }

                // Interpolate influence

                Real influence = startInfluence + t*(endInfluence - startInfluence);

                // Scale by animation weight

                influence = weight * influence;

                // Get pose

                assert (poseList && p1->poseIndex < poseList->size());

                Pose* pose = (*poseList)[p1->poseIndex];

                // apply

                applyPoseToVertexData(pose, data, influence);

            }

            // Now deal with any poses in key 2 which are not in key 1

            for (VertexPoseKeyFrame::PoseRefList::const_iterator p2 = poseList2.begin();

                p2 != poseList2.end(); ++p2)

            {

                bool found = false;

                for (VertexPoseKeyFrame::PoseRefList::const_iterator p1 = poseList1.begin();

                    p1 != poseList1.end(); ++p1)

                {

                    if (p1->poseIndex == p2->poseIndex)

                    {

                        found = true;

                        break;

                    }

                }

                if (!found)

                {

                    // Need to apply this pose too, scaled from 0 start

                    Real influence = t * p2->influence;

                    // Scale by animation weight

                    influence = weight * influence;

                    // Get pose

                    assert (poseList && p2->poseIndex <= poseList->size());

                    constPose* pose = (*poseList)[p2->poseIndex];

                    // apply

                    applyPoseToVertexData(pose, data, influence);

                }

            } // key 2 iteration

        } // morph or pose animation

}

 

 

Animation(动画)

  一个动画由多个动画轨迹(AnimationTrack)组成,而一个动画轨迹可以控制一个节点,这样一个动画可以使得多个节点沿着自己的轨迹运动。

Animatiion不能自己直接创建,应该通过拥有Animation的父物体来调用,如Skeleton

关键函数和成员变量如下:

class_OgreExportAnimation : publicAnimationAlloc {

 

public:

        /** The types of animation interpolation available. */

        enumInterpolationMode

        {

            /** Values are interpolated along straight lines. */

            IM_LINEAR,                线性插值

            /** Values are interpolated along a spline, resulting in smoother changes in direction. */

            IM_SPLINE                样条插值

        };

 

        /** The types of rotational interpolation available. */

        enumRotationInterpolationMode

        {

            /** Values are interpolated linearly. This is faster but does not

                necessarily give a completely accurate result.

            */

            RIM_LINEAR,                     线性插值

            /** Values are interpolated spherically. This is more accurate but

                has a higher cost.

            */

            RIM_SPHERICAL                   样条插值

 

        };

Animation管理三个Track,所以有一系列的函数都是跟这三种Track相关的

        NodeAnimationTrack* createNodeTrack(void);

        NumericAnimationTrack* createNumericTrack(unsignedshorthandle);

VertexAnimationTrack* createVertexTrack(unsignedshorthandle, VertexAnimationTypeanimType);

 

apply相关函数

void apply(RealtimePos, Realweight = 1.0, Realscale = 1.0f);

void applyToNode(OldNode* node, RealtimePos, Realweight = 1.0, Realscale = 1.0f);

void apply(Skeleton* skeleton, RealtimePos, Realweight = 1.0, Realscale = 1.0f);

void apply(Skeleton* skeleton, RealtimePos, floatweight,

         constAnimationState::BoneBlendMask* blendMask, Realscale);

        void apply(Entity* entity, RealtimePos, Realweight, boolsoftware,

            boolhardware);

void applyToAnimable(constAnimableValuePtr& anim, RealtimePos, Realweight = 1.0, Realscale = 1.0f);

void applyToVertexData(VertexData* data, RealtimePos, Realweight = 1.0);

 

apply具体代码:应用到Animation里的所有Track

voidAnimation::apply(RealtimePos, Realweight, Realscale)

    {

        _applyBaseKeyFrame();

 

        // Calculate time index for fast keyframe search

        TimeIndex timeIndex = _getTimeIndex(timePos);

 

        {

             NodeTrackList::iterator i;

             for (i = mNodeTrackList.begin(); i != mNodeTrackList.end(); ++i)

             {

                 (*i)->apply(timeIndex, weight, scale);

             }

        }

        {

             OldNodeTrackList::iterator i;

             for (i = mOldNodeTrackList.begin(); i != mOldNodeTrackList.end(); ++i)

             {

                 i->second->apply(timeIndex, weight, scale);

             }

        }

        NumericTrackList::iterator j;

        for (j = mNumericTrackList.begin(); j != mNumericTrackList.end(); ++j)

        {

            j->second->apply(timeIndex, weight, scale);

        }

        VertexTrackList::iterator k;

        for (k = mVertexTrackList.begin(); k != mVertexTrackList.end(); ++k)

        {

            k->second->apply(timeIndex, weight, scale);

        }

 

}

AnimationState(动画状态)

用来控制动画播放

       成员变量以下:

String mAnimationName;

        AnimationStateSet* mParent;

        Real mTimePos;

        Real mLength;

        Real mWeight;

        bool mEnabled;

        bool mLoop;

 

构造函数:参数意义: animName动画状态的名字,parent属于哪个AnimationStateSet,timepos在时间线的那个位置,length动画时间长度,weight动画状态的权重,enabled是否可以播放,true则可以播放

        AnimationState(constString& animName, AnimationStateSet *parent,

            RealtimePos, Reallength, Realweight = 1.0, boolenabled = false);

其他函数大多都是对成本变量的setget操作

 

以一个人行走为例,要想使人能够行走,必须在这个人模型上设置一些特真点,然后让这些点在每一帧按照一定的规则进行动,从而改变整个模型的状态。

在ogre里面,Keyframe类描述的是一个特征点(一个结点、一根骨头、一个顶点)的某一个关键帧的状态(位置、缩放、朝向等)和对应的时间点。

一个可驱动点的所有keyframe组合成一个track,每个可驱动点都有一个他的track,这就好比某个点在整段动画中的轨迹,其中keyframe要由track来创建。

多个track组合在一起就成为了一段动画,用Animation类来表示,这就是一个动画,例如对于骨骼动画,他的每一个骨头都有一个track,那么所有的骨头的track的组合在一起也就是整个骨骼动画了。track由Animation来创建。Animation则可以通过skeleton或者scenenmanager等来创建。

AnimationSate类:通常我们操控一段动画的播放等都不是直接操纵animation

 类,而是通过一个类AnimationState,它是animation的一个实例,通过场景管理器创建某个animation的一个animationState,然后就可以利用这个animationstate来播放这个animation了。


下面是一个例子

 void CreateAnimation()

      ...{

          /**//*首先我们考虑怎样可以把动画应用到当前摄像机上。

           因为一个动画可以应用到一个节点上,所以可以创建

           一个节点并将当前摄像机attach到这个节点上去*/

         SceneNode* camNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();

         camNode->attachObject(mCamera);

 

         //下面定义动画、动画轨迹以及关键帧:

         // 定义动画,指定动画的名称及长度(这里为10秒)

         Animation* anim = mSceneMgr->createAnimation("CameraTrack", 10);

         // 指定动画关键帧之间的插值方式(包括线性插值和样条插值)

            anim->setInterpolationMode(Animation::IM_SPLINE);

         // 定义动画的一个动画轨迹,并指定这个轨迹是作用到camNode节点上的

         NodeAnimationTrack* track = anim->createNodeTrack(0, camNode);

         // 定义动画轨迹包含的关键帧,下面定义了四个关键帧,加上起始帧

         // 五个关健帧形成了一个翻转的动画。

         TransformKeyFrame* key = track->createNodeKeyFrame(0); // startposition

         key = track->createNodeKeyFrame(2.5);

         key->setTranslate(Vector3(500,500,-1000));

         key = track->createNodeKeyFrame(5);

         key->setTranslate(Vector3(-1500,1000,-600));

         key = track->createNodeKeyFrame(7.5);

         key->setTranslate(Vector3(0,-100,0));

         key = track->createNodeKeyFrame(10);

         key->setTranslate(Vector3(0,0,0));       

 

         //然后定义AnimationState类的对象,它和刚才定义的动画类相对应。设置动画的状态为启用:

         mAnimState = mSceneMgr->createAnimationState("CameraTrack");

         mAnimState->setEnabled(true);    // 启用该动画

         //到此,初始化工作就做完了。

     }



 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值