OSG Animation Library Animation Analysis (iii)

Source: Internet
Author: User
Tags addchild reset

Through the previous two articles, basically to osganimation the entire implementation of the animation system has a relatively complete introduction, this article mainly introduces some other aspects of the animation, including the right, priority, and animation in the order of the transformation of the content. 1. Weight of the animation (weight)

Assuming that two forces are applied to a car running at a constant speed, one force makes the car move to the northeast in 60 km/h and the other to the northwest at 100 km/h, and if the direction of the car is to be corrected for North direction, Need to apply a weight of less than 1.0 to the Northwest, so that it is equal to the strength of the northeast direction, which is the meaning of motion superposition and weighting. This process is somewhat analogous to the addition of vectors, which follows the parallelogram rule, which is similar to a vector multiplied by a scalar. 1.1 Settings for weights

In Osganimation, the classes associated with weights should be:
1. Animationmanagerbase and its derived classes
2. Animation
3. Channel
4. Target
This means that channel and target do not have the interface to set weights, but in their internal need to use the weight of this parameter to participate in the operation, in other words, their weights are animation set to them. Animation can set the weight of the animation by setting the function void Animation::setweight (float weight), the animation management class Basicanimationmanager using void Playanimation ( animation* panimation, int priority = 0, float weight = 1.0), specifies the weight of the animation. Assuming that you use Basicanimationmanager to write animation code, the transfer relationship of the weight setting is:

That is, the weights specified in the playanimation are set to Animation,animation to traverse all the channels it manages and set this weight to these channels " In other words, the weights of all channels in the same animation are the same ", these channels set the weights to the respective target objects it manages, and the target object uses the weights of this setting to calculate the final result. 1.2 Single animation single channel

In the previous example of writing a Rotatecallback, a channel was added to an animation, and if the weights were set, the results would be affected. The code is as follows:

int main (int argc, char **argv) {osgviewer::viewer Viewer;

    osg::group* grp = new Osg::group;

    Osg::matrixtransform *mt = new Osg::matrixtransform;
    Osganimation::updatematrixtransform *umt1 = new Osganimation::updatematrixtransform;
    Umt1->setname ("Move1updatedatecallback");

    Umt1->getstackedtransforms (). push_back (New Osganimation::stackedtranslateelement ("move1"));
    Osganimation::vec3linearchannel *channel1 = new Osganimation::vec3linearchannel ();
    Channel1->settargetname ("Move1updatedatecallback");
    Channel1->setname ("move1"); Channel1->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (
    0, OSG::VEC3 (0, 0, 0)); Channel1->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (

    2, OSG::VEC3 (5, 0, 0));
    Osganimation::animation *anim1 = new Osganimation::animation ();

    Anim1->addchannel (CHANNEL1); Osganimation::basicanimationmanaGer *bam = new Osganimation::basicanimationmanager ();
    Bam->registeranimation (ANIM1);

    Bam->playanimation (ANIM1, 10, 0.5);
    osg::node* Cownode = Osgdb::readnodefile ("COW.OSG");
    Grp->addchild (MT);
    Mt->addchild (Cownode);

    Grp->addupdatecallback (BAM);

    Mt->addupdatecallback (UMT1);
    Viewer.setscenedata (GRP);
    Viewer.setupviewinwindow (300, 300, 800, 600);
Return (Viewer.run ()); }

Use Playanimation to set the current animation weight is 0.5, the priority is 10 (default parameter weight=0.5, priority=0), through 1.1 in the weight of the setting, you can eventually get
The weight code portion of the channel:

        virtual void update (double time, float weight, int priority)
        {
            //skip if weight = = 0
            if (weight < 1e-4) 
  return;
            TypeName Samplertype::usingtype value;
            _sampler->getvalueat (time, value);
            _target->update (weight, value, priority);
        }

If you set a weight less than (0.00001, which is approximately equal to 0), then the animation will not work. Set other values, and the code goes into the code for the target recalculation:

        void update (float weight, const t& val, int priority)
        {
            if (_weight | | _priorityweight)
            {
                if (_LASTPR Iority! = Priority)
                {
                    _weight + = _priorityweight * (1.0-_weight);
                    _priorityweight = 0;
                    _lastpriority = priority;
                }

                _priorityweight + = weight;
                Float T = (1.0-_weight) * weight/_priorityweight;
                Lerp (T, _target, Val);
            }
            else
            {
                _priorityweight = weight;
                _lastpriority = priority;
                _target = val;
            }
        }

Let's take a look at the target class's saved and priority and weight-related variables

    Class  Target:public osg::referenced
    {public
    :
        Target (): _weight (0), _priorityweight (0), _ Lastpriority (0) {}
        Virtual ~target () {}
        void Reset () {_weight = 0; _priorityweight = 0;}
        int GetCount () const {return referencecount ();}
        float Getweight () const {return _weight;}
    Protected:
        float _weight;
        float _priorityweight;
        int _lastpriority;
    };

The meanings of these three variables _weight, _priorityweight, _lastpriority are:
_weight: The current calculated weights, if the animation manager is managed by priority order, then when the priority is switched, _weight will record the weight of all previous priority animations (if the entire weight is considered to be 1)
_priorityweight: Refers to the sum of the weights of all the channels under which a priority is traversed. When the priority switches, this value is set to 0, and the calculation starts again. (This is also why the name is Priorityweight, because it only records the sum of the weights below a certain priority)
_lastpriority is the last priority (by logging the last priority, you can know when the priority has switched)
These three variables are 0 by default, and _weight and _priorityweight can be set to 0 by calling the Reset function.
When single-animation single channel, the Basicanimationmanager update code is as follows:

void Basicanimationmanager::update (double time)
{
    ...
    for (Targetset::iterator it = _targets.begin (); It! = _targets.end (); ++it)
        (*it). Get ()->reset ();
    for (Animationlayers::reverse_iterator Iteranim = _animationsplaying.rbegin (); Iteranim! = _animationsplaying.rend (); ++iteranim)
    {
        //update all animation
        INT-priority = iteranim->first;
        animationlist& list = iteranim->second;
        for (unsigned int i = 0; i < list.size (); i++)
        {
            list[i]->update (time, priority)
        }
    }
    ... c16/>}

The entire traversal loop actually traverses only once, because there is only one animation with a priority of 0, and only one channel in the animation, this loop executes only once, note that the reset operation of Target is performed before the update is performed, and the _weight and _ The priorityweight is set to 0, which causes target to return only the interpolated values in the channel when the update is executed.

            else
            {
                _priorityweight = weight;
                _lastpriority = priority;
                _target = val;
            }

There is no weighting to participate in the calculation.
In the case of single-animation single-channel:
1. Set the weight does not work, but do not set to 0 (to be exact is not less than 1e-4)
2. The priority of the setting does not have any effect
3. Target only helps to pass data, passing data in channel sampler to Updatematrixtransform 1.2 single-animated multi-channel

Since the animation animation is used to manage many channel, try to add multiple channel in animation:

int main (int argc, char **argv) {osgviewer::viewer Viewer;

    osg::group* grp = new Osg::group;

    Osg::matrixtransform *mt = new Osg::matrixtransform;
    Osganimation::updatematrixtransform *umt1 = new Osganimation::updatematrixtransform;
    Umt1->setname ("Move1updatedatecallback");

    Umt1->getstackedtransforms (). push_back (New Osganimation::stackedtranslateelement ("move1"));
    Channel 1 Osganimation::vec3linearchannel *channel1 = new Osganimation::vec3linearchannel ();
    Channel1->settargetname ("Move1updatedatecallback");
    Channel1->setname ("move1"); Channel1->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (
    0, OSG::VEC3 (0, 0, 0)); Channel1->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (

    2, OSG::VEC3 (5, 0, 0));
    Channel 2 Osganimation::vec3linearchannel *channel2 = new Osganimation::vec3linearchannel (); Channel2->settaRgetname ("Move1updatedatecallback");
    Channel2->setname ("move1"); Channel2->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (
    0, OSG::VEC3 (0, 0, 0)); Channel2->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (

    2, OSG::VEC3 (0, 0, 5));
    Osganimation::animation *anim1 = new Osganimation::animation ();
    Anim1->addchannel (CHANNEL1);

    Anim1->addchannel (CHANNEL2);
    Osganimation::basicanimationmanager *bam = new Osganimation::basicanimationmanager ();
    Bam->registeranimation (ANIM1);

    Bam->playanimation (ANIM1);
    osg::node* Cownode = Osgdb::readnodefile ("COW.OSG");
    Grp->addchild (MT);
    Mt->addchild (Cownode);

    Grp->addupdatecallback (BAM);

    Mt->addupdatecallback (UMT1);
    Viewer.setscenedata (GRP);
    Viewer.setupviewinwindow (300, 300, 800, 800);
Return (Viewer.run ()); }

Run the modification program and discover that the model is moving to the top right of the screen, with the combination of two channels (Channel1 to the right and Channel2 up).
As the weight of the same animation is the same, that is, all the channels under the animation weight is the same. The updatematrixtransform contains only one stackedtranslateelement, and the stackedtranslateelement is connected by two channels, so the target is shared with the two. The code to use the recalculation from Target can be known:
1. Target's _weight and _priorityweight are set to 0 in each traversal, and if all channel priorities are unchanged, then the _weight in target will always be 0, The following code will never be executed (1.2 in single animation because all animation channels under the same priority, so the following code will not be executed)

                if (_lastpriority! = Priority)
                {//change in priority
                    //Add to weight with the same previous priority Cumula Ted Weight
                    _weight + = _priorityweight * (1.0-_weight);
                    _priorityweight = 0;
                    _lastpriority = priority;
                }
The first channel that is traversed will definitely execute the statement in else, i.e. (the first loop must go to the Else branch)
            else
            {
                _priorityweight = weight;
                _lastpriority = priority;
                _target = val;
For this example, the update code for target is executed two times, because _weight = 0, the actual code is as follows:
                _priorityweight + = weight;
                float T =  weight/_priorityweight;
                Lerp (T, _target, Val);

Lerp is a linear difference, and this line of LERP is
_target = _target * (1-t) + T * val;
Since all the weight in a animation are equal, that is, the t=0.5, assuming that there is more than one channel in a animation, then T is equal to 1/2, 1/3, 1/4, ... Know the number of 1/channel.

If the weights are the same, then the final value of an animation should be:
Final value = 1/n * Channel1 value + 1/n Channel2 value + ... + 1/n Channeln value.
Use this code to get this conclusion.

The calculation and derivation of this code is simple to say:

Suppose that there are N channel in an animated animation, since the weights and priorities of these channel are the same, assuming that their weight is w, and that each channel is computed by its sampler sampler as the result of V, The result of the final calculation (stored by target) is value, then the code is evaluated as follows:

First iteration: value = V1 (_priorityweight = w)

Second iteration: Because _priorityweight = _priorityweight + W, which is _priorityweight = 2w, then there is: Value = (1-W/2 * w) v1 + v2 W = 1/2* (v1+ V2)

Third iteration: Same value = (1-w/3*w) (0.5 (V1+V2)) + 1/3 cv3 = 1/3* (v1+v2+v3)
......

Nth iteration: value = [1− (1/n)]∗ (1/n−1) ∗ (v1+v2+...+vn−1) + (1/n) ∗VN [1-(1/n)]* (1/n-1) * (v1+v2+...+v_{n-1}) + (1/n) * V_{n} = 1/n * (V1+v2+...+v_n)

This means that when there are multiple channels in an animation, there are the following conclusions:
1. The weights and priorities of all channels can only be set by animation, and the weights are the same, and the priority is the same.
2. The weight cannot be set to 0 (specifically not less than 1e-4), otherwise the update function exits directly. In addition, the weight is set to any other number is the same effect
3. The final result is the average of all channels 2. Priority of the animation

Osganimation Animation manager Basicanimationmanager in the animation of the array, it is stored with a map, the map's key value is the priority of the animation, by default, added to the animation priority is 0, When using void Playanimation (animation* panimation, int priority = 0, float weight = 1.0), set the precedence when playing. According to the previous discussion, the priority is only meaningful when there are multiple animations. 2.1 Multi-animation single channel

Multi-animation single channel refers to the manager Basicanimationmanager add a lot of animation animation, each animation contains only one channel, modify the code:

int main (int argc, char **argv) {osgviewer::viewer Viewer;

    osg::group* grp = new Osg::group;

    Osg::matrixtransform *mt = new Osg::matrixtransform;
    Osganimation::updatematrixtransform *umt1 = new Osganimation::updatematrixtransform;
    Umt1->setname ("Move1updatedatecallback");


    Umt1->getstackedtransforms (). push_back (New Osganimation::stackedtranslateelement ("move1"));
    The first animation Osganimation::vec3linearchannel *channel1 = new Osganimation::vec3linearchannel ();
    Channel1->settargetname ("Move1updatedatecallback");
    Channel1->setname ("move1"); Channel1->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (
    0, OSG::VEC3 (0, 0, 0)); Channel1->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (
    2, OSG::VEC3 (5, 0, 0));
    Osganimation::animation *anim1 = new Osganimation::animation ();

    Anim1->addchannel (CHANNEL1); A second animated OsganimaTion::vec3linearchannel *channel2 = new Osganimation::vec3linearchannel ();
    Channel2->settargetname ("Move1updatedatecallback");
    Channel2->setname ("move1"); Channel2->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (
    0, OSG::VEC3 (0, 0, 0)); Channel2->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (
    2, OSG::VEC3 (0, 0, 5));
    Osganimation::animation *anim2 = new Osganimation::animation ();

    Anim2->addchannel (CHANNEL2);
    A third animation//second animation Osganimation::vec3linearchannel *channel3 = new Osganimation::vec3linearchannel ();
    Channel3->settargetname ("Move1updatedatecallback");
    Channel3->setname ("move1"); Channel3->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (
    0, OSG::VEC3 (0, 0, 0)); Channel3->getorcreatesampler ()->getorcreatekeyframecontainer ()->push_back (OsgAnimation::Vec3Keyframe (2, OSG::VEC3 (0, 5, 0)));
    Osganimation::animation *anim3 = new Osganimation::animation ();

    Anim2->addchannel (CHANNEL3); Osganimation

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.