Animation mixing in ogre)

Source: Internet
Author: User
Tags add time

There are very few Chinese ogre documents on the Internet. I hope to help beginners by sharing what I learned.

The implementation of bone animation in ogre is really simple. There are two functions: getanimationstate and addtime. OK, the characters can be moved. This animationblender class can fade from one animation to another in multiple ways, from an article on the Ogre website. But the foreigner only posted the Code, without explaining it, or even without detailed comments in the Code. cainiao like me can only taste it slowly.

The following is the definition of the animationblender class:

# Pragma once
# Ifndef animationblender_incl
# Define animationblender_incl

# Include <ogre. h>
Using namespace ogre;
Class animationblender
{
Public:
Enum blendingtransition // different mixing Modes
{
Blendswitch, // directly switch to the target Animation
Blendwhileanimating, // fade-in and fade-out (the source animation proportion is reduced, and the target animation proportion is increased)
Blendthenanimate // fade out the source animation to the first frame of the target animation, and then start the target Animation
};

PRIVATE:
Entity * mentity;
Animationstate * msource;
Animationstate * mtarget;

Blendingtransition mtransition;

Bool loop; // whether to loop

~ Animationblender (){}

Public:
Real mtimeleft, mduration; // duration

Bool complete;

Void blend (const string & animation, blendingtransition transition, real duration, bool L );
Void addtime (real );
Real getprogress () {return mtimeleft/mduration ;}
Animationstate * getsource () {return msource ;}
Animationstate * gettarget () {return mtarget ;}
Animationblender (entity *);
Void Init (const string & animation );
};

# Endif
Several mixed methods are defined here, and different effects can be seen after running. The constructor accepts an entity pointer, and then we can operate the animation in this entity.
Implementation of the animationblender class:

# Include "animationblender. H"

Void animationblender: Init (const string & animation)
{
// Initialize the animationstate of all actions
Animationstateset * Set = mentity-> getallanimationstates ();
Animationstateiterator it = set-> getanimationstateiterator ();
While (it. hasmoreelements ())
{
Animationstate * anim = it. getnext ();
Anim-> setenabled (false );
Anim-> setweight (0 );
Anim-> settimeposition (0 );
}
// Initialize msource
Msource = mentity-> getanimationstate (animation );
Msource-> setenabled (true );
Msource-> setweight (1 );
Mtimeleft = 0;
Mduration = 1;
Mtarget = 0;
Complete = false;
}
Void animationblender: blend (const string & animation, blendingtransition transition, real duration, bool L)
{
Loop = L; // you can specify whether a loop is required.
If (transition = animationblender: blendswitch)
{// If the mixed mode is directly switched, change the msource.
If (msource! = 0)
Msource-> setenabled (false );
Msource = mentity-> getanimationstate (animation );
Msource-> setenabled (true );
Msource-> setweight (1 );
Msource-> settimeposition (0 );
Mtimeleft = 0;
}
Else
{
// Obtain the new animation state first
Animationstate * newtarget = mentity-> getanimationstate (animation );
If (mtimeleft> 0) // The previous mixing has not ended.
{
If (newtarget = mtarget)
{
// The new target is the target in the hybrid process and does nothing.
}
Else if (newtarget = msource)
{
// The new target is the source animation and go back directly.
Msource = mtarget;
Mtarget = newtarget;
Mtimeleft = mduration-mtimeleft;
}
Else
{
// Now newtarget is a new animation.
If (mtimeleft <mduration * 0.5) // The Last mixing progress is not more than half
{
// Simply replace the target.
Mtarget-> setenabled (false );
Mtarget-> setweight (0 );
}
Else // if more than half of the time has elapsed, the old target becomes the new source
{

Msource-> setenabled (false );
Msource-> setweight (0 );
Msource = mtarget;
}
Mtarget = newtarget;
Mtarget-> setenabled (true );
Mtarget-> setweight (1.0-mtimeleft/mduration );
Mtarget-> settimeposition (0 );
}
}
Else // The Last mixing has ended and is not in the mixed state.
{
Mtransition = transition;
Mtimeleft = mduration = duration;
Mtarget = newtarget;
Mtarget-> setenabled (true );
Mtarget-> setweight (0 );
Mtarget-> settimeposition (0 );
}
}
}
Void animationblender: addtime (real time)
{
If (msource! = 0) // if there is no animationstate, no operation is performed.
{
If (mtimeleft> 0) // The two animations are still being mixed.
{
Mtimeleft-= time;
If (mtimeleft <0)
{
// After mixing, switch to the target Animation
Msource-> setenabled (false );
Msource-> setweight (0 );
Msource = mtarget;
Msource-> setenabled (true );
Msource-> setweight (1 );
Mtarget = 0;
}
Else
{
// Change the weight of the two animations while they are still in the mixed state
Msource-> setweight (mtimeleft/mduration );
Mtarget-> setweight (1.0-mtimeleft/mduration );
// In this hybrid mode, you need to add time for the target animation.
If (mtransition = animationblender: blendwhileanimating)
Mtarget-> addtime (time );
}
}
If (msource-> gettimeposition ()> = msource-> getlength ())
{
Complete = true;
}
Else
{
Complete = false;
}
Msource-> addtime (time );
Msource-> setloop (loop );
}
}
Animationblender: animationblender (entity * entity): mentity (entity ){}

To use this animationblender class.
Declare a global blender instance first

Animationblender * blender;

Initialize it in createscene.

// Instantiate a blender and pass the entity
Blender = new animationblender (ninjahead );
// Set an initial action
Blender-> Init ("idle1 ");

Add time for blender in framestarted
Blender-> addtime (EVT. timesincelastframe );
Now ninja can be activated.
Then we use the keyboard to control the animation:
Override the keyboard input function of the parent class in framelistener

Virtual bool processunbufferedkeyinput (const frameevent & EVT)
{
If (minputdevice-> iskeydown (kc_t ))
{
Blender-> blend ("attack1", animationblender: blendwhileanimating, 1.0, false );
}

If (minputdevice-> iskeydown (kc_j ))
{
Blender-> blend ("jump", animationblender: blendwhileanimating, 1.0, false );
}

If (minputdevice-> iskeydown (kc_ I ))
{
Blender-> blend ("idle1", animationblender: blendwhileanimating, 1.0, false );
}
// Remember to call the keyboard processing of the parent class to make wasd still available
Return exampleframelistener: processunbufferedkeyinput (EVT );
}

You can see the effect. You can also try other mixed methods.
The complete code is as follows:

# Ifndef _ animblender_h _
# DEFINE _ animblender_h _

# Include "exampleapplication. H"
# Include "../animationblender. H"

Animationblender * blender;

Class animblenderframelistener: Public exampleframelistener
{
PRIVATE:
Scenemanager * mscenemgr;
Public:
Animblenderframelistener (scenemanager * scenemgr, renderwindow * Win, Camera * cam)
: Exampleframelistener (Win, Cam ),
Mscenemgr (scenemgr)
{
}

Bool framestarted (const frameevent & EVT)
{
Bool ret = exampleframelistener: framestarted (EVT );
Blender-> addtime (EVT. timesincelastframe );

Return ret;

}
// Override the keyboard input function of the parent class
Virtual bool processunbufferedkeyinput (const frameevent & EVT)
{
If (minputdevice-> iskeydown (kc_t ))
{
Blender-> blend ("attack1", animationblender: blendwhileanimating, 1.0, false );
}

If (minputdevice-> iskeydown (kc_j ))
{
Blender-> blend ("jump", animationblender: blendwhileanimating, 1.0, false );
}

If (minputdevice-> iskeydown (kc_ I ))
{
Blender-> blend ("idle1", animationblender: blendwhileanimating, 1.0, false );
}
// Remember to call the keyboard processing of the parent class to make wasd still available
Return exampleframelistener: processunbufferedkeyinput (EVT );
}
};

 

Class animblenderapp: Public exampleapplication
{
Public:
Animblenderapp ()
{}

~ Animblenderapp ()
{
}

Protected:

Virtual void createcamera (void)
{
// Create the camera
Mcamera = mscenemgr-> createcamera ("playercam ");

// Position it at 500 in z direction
Mcamera-> setposition (vector3 (0, 0, 180 ));
// Look back along-z
Mcamera-> lookat (vector3 (300 ));
Mcamera-> setnearclipdistance (5 );
}

 

// Just override the mandatory create scene Method
Virtual void createscene (void)
{

Entity * ninjahead = mscenemgr-> createentity ("ninja", "ninja. mesh ");

Scenenode * ninjanode = mscenemgr-> getrootscenenode ()-> createchildscenenode ();
Ninjanode-> attachobject (ninjahead );

// Set ambient light
Mscenemgr-> setambientlight (colourvalue (0.5, 0.5, 0.5 ));

// Create a light
Light * l = mscenemgr-> createlight ("mainlight ");
L-> setposition (20, 80, 50 );

// Instantiate a blender and pass the entity
Blender = new animationblender (ninjahead );
// Set an initial action
Blender-> Init ("idle1 ");
}

// Create new frame listener
Void createframelistener (void)
{
Mframelistener = new animblenderframelistener (mscenemgr, mwindow, mcamera );
Mroot-> addframelistener (mframelistener );
}
};

# Endif // # ifndef _ animblender_h _

Csdn does not support inserting C ++ code, leading to messy code and angry ing ....... If you want to directly copy the code and paste it into vs, remember to press Alt + F8 and the code will be automatically organized.

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.