OSG Animation Library Animation analysis (II.)

Source: Internet
Author: User
Tags addchild

As discussed in the previous article, the target object in Osganimation should have some relationship with the update callback of the scene, which is discussed earlier in this paper.

In the preceding code, using the update callback class that you wrote Rotatecallback,osganimation, depending on the content and manner of the animation, provides an update callback class for several animations. Updatematrixtransform and Updatemorph (animation callbacks to describe positional changes), Updatematerial (animation callbacks for material changes) 1. Updatematrixtransform

In the previous rotatecallback, set it to a scene node Osg::matrixtransform update callback, this is Updatematrixtransform is also such a class, it inherits with Osg::nodevisitor , the implementation of the Operator method is as follows:

void Updatematrixtransform::operator () (osg::node* Node, osg::nodevisitor* nv)
{
    if (NV && nv-> Getvisitortype () = = Osg::nodevisitor::update_visitor)
    {
        osg::matrixtransform* matrixtransform = dynamic_ cast<osg::matrixtransform*> (node);
        if (MatrixTransform)
        {
            //Here we would prefer to has a flag inside transform stack in order to avoid update and A dirty state in MatrixTransform if it's not require.
            _transforms.update ();
            Const osg::matrix& Matrix = _transforms.getmatrix ();
            Matrixtransform->setmatrix (matrix);
        }
    }
    Traverse (NODE,NV);
}

The implementation of the code is similar to the previous rotatecallback, except that the rotation matrix matrix is computed, and Rotatecallback uses target to get it, And the real calculation process in the Interpolator (through animation to obtain the channel and then get sampler finally get to the interpolator, calculate the result). The calculation of the Updatematrixtransform matrix is obtained by an array of _transforms, which is an array of stackedtransformelement.

According to the previous assumption, the value of the keyframe required by the scene is obtained from the target, and the Updatematrixtransform should also follow this rule, as a matter of fact, Stackedtransformelement provides some interfaces for manipulating the target.

    Class  Stackedtransformelement:public osg::object
    {public
    :
        virtual void Applytomatrix (Osg::matrix & matrix) const = 0;
        Virtual target* Getorcreatetarget () {return 0;}
        Virtual target* Gettarget () {return 0;}
        Virtual const target* Gettarget () const {return 0;}
    };

Depending on the type of animation, many different types of stackedtransformelement subclasses are derived, mainly including:

The rotatecallback corresponds to the stackedrotateaxiselement here.

    Class Osganimation_export Stackedrotateaxiselement:public stackedtransformelement {public:meta_obj

        ECT (osganimation, stackedrotateaxiselement);
        Stackedrotateaxiselement ();
        Stackedrotateaxiselement (const stackedrotateaxiselement&, const osg::copyop&);
        Stackedrotateaxiselement (const std::string& name, const osg::vec3& axis, double angle);

        Stackedrotateaxiselement (const osg::vec3& axis, double angle);
        void Applytomatrix (osg::matrix& Matrix) const;
        Osg::matrix Getasmatrix () const;
        BOOL Isidentity () const {return (_angle = = 0);}

        void Update (Float t = 0.0);
        Const osg::vec3& Getaxis () const;
        Double getangle () const;
        void Setaxis (const osg::vec3&);

        void Setangle (double);
        Virtual target* getorcreatetarget ();
        Virtual target* Gettarget () {return _target.get ();} Virtual const target* Gettarget () const {return _target.geT ();}
        PROTECTED:OSG::VEC3 _axis;
        Double _angle;
    Osg::ref_ptr<floattarget> _target; };

All of these derived classes implement the abstract function Applytomatrix in the base class, and this function plays a real role, and the stackedrotateaxiselement is implemented as follows:

void Stackedrotateaxiselement::applytomatrix (osg::matrix& Matrix) const 
{    
    matrix.premultrotate (OSG:: Quat (_angle, _axis)); 
}

The incoming matrix rotates once on its original basis.

After the introduction of the Updatematrixtransform, the former program, using this callback instead of Rotatecallback, the code is as follows:

int main () {osg::ref_ptr<osgviewer::viewer> Viewer = new Osgviewer::viewer;

    osg::ref_ptr<osg::node> Cownode = Osgdb::readnodefile ("COW.OSG");
    osg::ref_ptr<osg::matrixtransform> root = new Osg::matrixtransform;

    Root->addchild (Cownode);
    Osganimation::D oublekeyframe keyframe1 (0.0, 0.0);

    Osganimation::D oublekeyframe keyframe2 (10.0, OSG::P i * 2); Osg::ref_ptr<osganimation::D oublekeyframecontainer> keyframecontainer = new osganimation::D
    Oublekeyframecontainer ();
    Keyframecontainer->push_back (KEYFRAME1);
    Keyframecontainer->push_back (keyframe2);
    Osg::ref_ptr<osganimation::D oublelinearsampler> sampler = new osganimation::D Oublelinearsampler ();
    Sampler->setkeyframecontainer (Keyframecontainer.get ());
    Osg::ref_ptr<osganimation::D oublelinearchannel> channel = new osganimation::D Oublelinearchannel ();

    Channel->setsampler (Sampler.get ()); Osg::ref_ptr<osganimation::animation> Animation= new Osganimation::animation ();

    Animation->addchannel (Channel.get ());
    osg::ref_ptr<osganimation::updatematrixtransform> umt = new Osganimation::updatematrixtransform ();
    osg::ref_ptr<osganimation::stackedrotateaxiselement> srae = new Osganimation::stackedrotateaxiselement ();
    Srae->setaxis (Osg::z_axis);
    Srae->setangle (0.0);
    Umt->getstackedtransforms (). push_back (Srae);

    Root->addupdatecallback (UMT);
    Viewer->setupviewinwindow (200, 200, 800, 600);
    Viewer->setscenedata (root);
return Viewer->run (); }

After compiling the run, we found that the model in the scene did not change, which is why. Take a closer look at the discovery that there is no association between Osganimation::animation class and Updatematrixtransform, In other words, the animation of the real interpolation work does not pass the value of the intermediate frame to updatematrixtransform, More specifically, the result of animation interpolation is not passed to target in Stackedrotateaxiselement, That is to say, "link" the target and osganimation::animation in the Stackedrotateaxiselement, which is the Updatematrixtransform class in addition to calling operator ( ) is another function. 2. Links Animation and Nodecallback

By viewing the inheritance relationship of Updatematrixtransform

Two link pure virtual functions defined in Animationupdatecallbackbase:

    Class Animationupdatecallbackbase:public Virtual Osg::object
    {public
    :
        virtual bool Link (channel* Channel) = 0;
        virtual int link (animation* Animation) = 0;
    };

virtual int link (animation* Animation) = 0 is implemented in Animationupdatecallback, and is implemented by calling each channel in Animation to link, The rest of the work is to complete the bool link (channel* Channel) in the derived class, the Updatematrixtransform implementation:

bool updatematrixtransform::link (osganimation::channel* Channel) {Const std::string&

    ChannelName = Channel->getname (); Check if we can link a stackedtransformelement to the current Channel for (stackedtransform::iterator it = _TRANSFO Rms.begin (); It! = _transforms.end ();
        ++it) {stackedtransformelement* element = It->get ();
            if (element &&!element->getname (). Empty () && ChannelName = = Element->getname ()) {
            target* target = Element->getorcreatetarget ();
        if (target && channel->settarget) return true; }} osg_info << "Updatematrixtransform::link Channel" << channel->getname () << "does not C

    Ontain a symbolic name that can is linked to a stackedtransformelement. "<< Std::endl;
return false; }

This code is very critical, as mentioned in the end of the previous article (OSG Animation Library Animation parsing (a)), forcibly acquiring the target from the channel and capturing the value of the intermediate frame stored in the target, Again set to Rotatecallback the way is very unnatural, this job should not be let the developer to do, osganimation internal should deal with, this code explains osganimation how to do

From the implementation of the code, it is understood that target generation is responsible for stackedtransformelement, which will produce good target to channel and capture the result of key frame calculation from channel. The captured results do not need to be manually set by the developer to updatematrixtransform this callback, in Updatematrixtransform's Opeator () function through

  _transforms.update ();
  Const osg::matrix& Matrix = _transforms.getmatrix ();
  Matrixtransform->setmatrix (matrix);

Gets and sets the node that calls callback (that is, the matrixtransform in the scene), which alters the position and posture of the model. As a result, the whole animation of how many classes work together to drive a scene to update the animation process has been explained clearly.

Also note that in the process of setting the target to channel, the corresponding stackedtransformelement and channel associations are found by _transforms using the name of the channel, which means The name of the channel must be set at the time of the link and the name of the stackedrotateaxiselement, otherwise it will not correctly pass the target stackedrotateaxiselement generated to the channel, This causes the entire data transfer chain to fail.

Understand the above principle, modify the above program, modify the code as follows:

int main () {osg::ref_ptr<osgviewer::viewer> Viewer = new Osgviewer::viewer;

    osg::ref_ptr<osg::node> Cownode = Osgdb::readnodefile ("COW.OSG");
    osg::ref_ptr<osg::matrixtransform> root = new Osg::matrixtransform;

    Root->addchild (Cownode);
    Osganimation::D oublekeyframe keyframe1 (0.0, 0.0);

    Osganimation::D oublekeyframe keyframe2 (10.0, OSG::P i * 2); Osg::ref_ptr<osganimation::D oublekeyframecontainer> keyframecontainer = new osganimation::D
    Oublekeyframecontainer ();
    Keyframecontainer->push_back (KEYFRAME1);
    Keyframecontainer->push_back (keyframe2);
    Osg::ref_ptr<osganimation::D oublelinearsampler> sampler = new osganimation::D Oublelinearsampler ();
    Sampler->setkeyframecontainer (Keyframecontainer.get ());
    Osg::ref_ptr<osganimation::D oublelinearchannel> channel = new osganimation::D Oublelinearchannel ();
    Channel->setsampler (Sampler.get ());

    Channel->setname ("Rotatearoundzaxis"); Osg::ref_ptr<osganimation::animation> Animation = new Osganimation::animation ();

    Animation->addchannel (Channel.get ());
    osg::ref_ptr<osganimation::updatematrixtransform> umt = new Osganimation::updatematrixtransform ();
    osg::ref_ptr<osganimation::stackedrotateaxiselement> srae = new Osganimation::stackedrotateaxiselement ();
    Srae->setaxis (Osg::z_axis);
    Srae->setname ("Rotatearoundzaxis");
    Umt->getstackedtransforms (). push_back (Srae);
    Umt->link (Channel.get ());


    Root->addupdatecallback (UMT);
    Viewer->setupviewinwindow (200, 200, 800, 600);
    Viewer->setscenedata (root);
return Viewer->run (); }

Run the code and find that there is still no animation effect. Where is the problem? Through the modified code, the entire process required for the animation to run has been opened (the channel in the animation gets the value of the intermediate frame through the sampler sample inside the channel. The targets produced by the stackedrotateaxiselement array in Updatematrixtransform is passed to the channel to accept the value of the intermediate frame, and set to the host of the Updatematrixtransform (tree structure in the scene MatrixTransform)). Compared with the previous code found: Animation's Update method is not called, that is, "Everything is ready, only the east wind", there is no update time to drive the animation run, animation channel in the Update method is not called, There is no way to produce intermediate frame values.

Since there is no way to drive animation, you can "make" a drive, and you can call animation's Update method in this callback by adding a callback to the upper node of the MatrixTransform. "It is important to note that this node must be above the MatrixTransform, because OSG will traverse from the top of the tree, running each node Updatecallback, only starters in MatrixTransform to change, To let the matrixtransform bind this updatematrixtransform get calculated interpolation results, thereby changing the MatrixTransform ", modify the code as follows:

Class Dummydrivernodecallback:public Osg::nodecallback {public:dummydrivernodecallback (osgAnimation::Animation *dl
        s) {_starttick = Osg::timer::instance ()->tick ();
    _animation = DLS; } virtual void operator () (osg::node* Node, osg::nodevisitor* nv) {Double Currenttick = Osg::timer::insta
        NCE ()->tick ();

        Double elaspedtime = osg::timer::instance ()->delta_s (_starttick, Currenttick);
        _animation->resettargets ();
        _animation->setplaymode (Osganimation::animation::loop);
        _animation->update (Elaspedtime);

        _animation->setweight (1.0);
    Traverse (node, NV);
    } protected:osg::ref_ptr<osganimation::animation> _animation;
Double _starttick;

};
    int main () {osg::ref_ptr<osgviewer::viewer> Viewer = new Osgviewer::viewer;

    osg::ref_ptr<osg::node> Cownode = Osgdb::readnodefile ("COW.OSG"); Osg::ref_ptr<osg::matrixtransform> root = new Osg::matrixtransform;

    Root->addchild (Cownode);
    Osganimation::D oublekeyframe keyframe1 (0.0, 0.0);

    Osganimation::D oublekeyframe keyframe2 (10.0, OSG::P i * 2); Osg::ref_ptr<osganimation::D oublekeyframecontainer> keyframecontainer = new osganimation::D
    Oublekeyframecontainer ();
    Keyframecontainer->push_back (KEYFRAME1);
    Keyframecontainer->push_back (keyframe2);
    Osg::ref_ptr<osganimation::D oublelinearsampler> sampler = new osganimation::D Oublelinearsampler ();
    Sampler->setkeyframecontainer (Keyframecontainer.get ());
    Osg::ref_ptr<osganimation::D oublelinearchannel> channel = new osganimation::D Oublelinearchannel ();
    Channel->setsampler (Sampler.get ());
    Channel->setname ("Rotatearoundzaxis");

    Channel->settargetname ("Updatematrixcallback");
    osg::ref_ptr<osganimation::animation> Animation = new Osganimation::animation ();

    Animation->addchannel (channel); Osg::ref_ptr<osganimation::updatematrixtransform> umt = new Osganimation::updatematrixtransform ();
    Umt->setname ("Updatematrixcallback"); osganimation::stackedrotateaxiselement* srae = new Osganimation::stackedrotateaxiselement ("RotateAroundZAxis", OSG:
    : Z_axis, 0.0);
    Umt->getstackedtransforms (). push_back (Srae);
    osg::ref_ptr<osganimation::animationupdatecallbackbase> base = UMT;

    Base->link (animation);

    Root->addupdatecallback (UMT);
    osg::ref_ptr<osg::group> dummydrivergroup = new Osg::group;
    Dummydrivergroup->addupdatecallback (new Dummydrivernodecallback (animation));

    Dummydrivergroup->addchild (root);
    Viewer->setupviewinwindow (200, 200, 800, 600);
    Viewer->setscenedata (Dummydrivergroup);
return Viewer->run (); }

A crash occurs after the run, and after debugging it is found that the target variable of target is used in stackedrotateaxiselement, when linked to the channel (the Settarget function of the channel), The channel uses Doubletarget, which fails after the cast, resulting in a null value for the channel target. Modify the method either we write a stackedrotateaxiselement derived class that uses Doubletarget as a member variable, or for the sake of simplicity, modify the previous double type to float type, after which the code is modified as follows:

Class Dummydrivernodecallback:public Osg::nodecallback {public:dummydrivernodecallback (osgAnimation::Animation *dl
        s) {_starttick = Osg::timer::instance ()->tick ();
    _animation = DLS; } virtual void operator () (osg::node* Node, osg::nodevisitor* nv) {Double Currenttick = Osg::timer::insta
        NCE ()->tick ();

        Double elaspedtime = osg::timer::instance ()->delta_s (_starttick, Currenttick);
        _animation->resettargets ();
        _animation->setplaymode (Osganimation::animation::loop);
        _animation->update (Elaspedtime);

        _animation->setweight (1.0);
    Traverse (node, NV);
    } protected:osg::ref_ptr<osganimation::animation> _animation;
Double _starttick;



};
    int main () {osg::ref_ptr<osgviewer::viewer> Viewer = new Osgviewer::viewer;

    osg::ref_ptr<osg::node> Cownode = Osgdb::readnodefile ("COW.OSG"); OSG::REF_PTR&LT;OSG::MatrixTransform 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.