Manipulating Bones in running Animation

Problems building or running the engine, queries about how to use features etc.
Post Reply
macross
Gnoblar
Posts: 21
Joined: Tue Oct 15, 2002 9:56 am
Location: Frankfurt, Germany
Contact:

Manipulating Bones in running Animation

Post by macross »

ho ppl,

I am trying to do some character animation with OGRE ala Jedi Knight II.
While running I wanna bend the character forward an backward, depending on the angle the 3rd person camera has.

I suppose I could build 2 separate skeletal animations. One for walk cycle and one for bending forward/backward and let OGRE merge these additive.

But it would be faster if I could be able to apply the walk anim and then adjust the backbone for example to simulate forward/backward bending.

I tried this similar to following code:

Code: Select all

AnimState animState;
Bone backBone;
...

animState.addTime(...);
backBone.pitch(alpha);
But that did not work, because calculation of the new pose overwrites the backBone orientation.

It seems to me I am on the wrong track. ;)
Is there an way for doing this?

thx!
macross
Ivica Aracic
http://www.bytelords.de/
http://ispace.stribor.de/ - software visualization for Java
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post by sinbad »

Try creating your own Animation against the skeleton with a single AnimationTrack for the bone you want to animate; you'll need to also create 1 or 2 keyframes, perhaps the 2 extremes of back movement you want. When you create an entity against this, this new animation will appear in it's animation state.

At runtime, either use the time to interpolate between the 2 extremes of back movement and let OGRE blend it with the current animation, or if you want total control, alter the KeyFrame(s) too.
macross
Gnoblar
Posts: 21
Joined: Tue Oct 15, 2002 9:56 am
Location: Frankfurt, Germany
Contact:

Post by macross »

thx for the tip sinbad,

I will try it that way.

cheers!
macross
Ivica Aracic
http://www.bytelords.de/
http://ispace.stribor.de/ - software visualization for Java
irobot
Gnoblar
Posts: 10
Joined: Wed Mar 26, 2003 8:13 am
Location: Switzerland

On-the-fly Animation

Post by irobot »

@macross
I'm also interested in doing animation on-the-fly.
Would you be so kind to give some snippets when you have
some working code.

Thanx :)
macross
Gnoblar
Posts: 21
Joined: Tue Oct 15, 2002 9:56 am
Location: Frankfurt, Germany
Contact:

Re: On-the-fly Animation

Post by macross »

@irobot: sure, if it works :)
Ivica Aracic
http://www.bytelords.de/
http://ispace.stribor.de/ - software visualization for Java
macross
Gnoblar
Posts: 21
Joined: Tue Oct 15, 2002 9:56 am
Location: Frankfurt, Germany
Contact:

Post by macross »

@irobot:

I just submitted the patch for it right now.

Doing on-the-fly animations with Ogre robo for example would look like this:

Code: Select all

        Entity *ent = mSceneMgr->createEntity("robot", "robot.mesh");

        Mesh* m = ent->getMesh();
        Skeleton* skel = m->getSkeleton();
        Animation* anim = skel->getAnimation("Walk");        
        manuallyControlledBone = skel->getBone("Joint10");
        manuallyControlledBone->setManuallyControlled(true);
        anim->destroyTrack(manuallyControlledBone->getHandle());
manipulating manually controlled Bones:

Code: Select all

        mAnimState->addTime(evt.timeSinceLastFrame);
        manuallyControlledBone->yaw(evt.timeSinceLastFrame*100);
Ivica Aracic
http://www.bytelords.de/
http://ispace.stribor.de/ - software visualization for Java
irobot
Gnoblar
Posts: 10
Joined: Wed Mar 26, 2003 8:13 am
Location: Switzerland

manuallyControlledBone

Post by irobot »

Wow!

That is easy coding and the turning robot looks nice! This way we can add some random movements and additional control depending on the environment to the loaded animations. Nice work! :D

ThankYou macross!
User avatar
AZTEK
Gnoblar
Posts: 2
Joined: Wed Jun 04, 2003 5:15 am
Location: Indiana
Contact:

Post by AZTEK »

Yea thanks macross this will help out alot.
John (AZTEK) Downey
http://www.catdevnull.net

"Imagine a school with children that can read and write, but with teachers who cannot, and you have a metaphor of the Information Age in which we live." -Peter Cochrane
grusifix
Gnoblar
Posts: 6
Joined: Sat Feb 14, 2004 10:54 pm
Contact:

Post by grusifix »

I was playing with macross' code and came out with this

Code: Select all

	bool processUnbufferedKeyInput(const FrameEvent& evt)
    {

		if (mInputDevice->isKeyDown(KC_I))
        {
			Quaternion q = manuallyControlledBone->getWorldOrientation();
			
			if(q.z > -0.3) {
				manuallyControlledBone->roll(evt.timeSinceLastFrame*100);
				speed = evt.timeSinceLastFrame* q.z*(.5);
			}
        }

		if (mInputDevice->isKeyDown(KC_O))
        {
			Quaternion q = manuallyControlledBone->getWorldOrientation();

			if(q.z < 0.5) {
				manuallyControlledBone->roll(evt.timeSinceLastFrame*(-100));
				speed = evt.timeSinceLastFrame* q.z*2;
			}
        }

....
bool frameStarted(const FrameEvent& evt)
    {
        mAnimState->addTime(evt.timeSinceLastFrame + speed);
....
Now I have little problem. Robot looks great but if I press and hold I-key (or O) robot goes round-and-round. After I release and press again it works great. Does this have something to do with input system or isn't that quaternion up-to-date?

EDIT: Added stupid speeding up :oops:

Can't anyone help me out here? Or should I just be quiet and work it out?
User avatar
ls129
Kobold
Posts: 26
Joined: Sun Sep 28, 2003 2:12 am
x 1
Contact:

Post by ls129 »

FYI: if you use the the latest CVS release, the traditional way of accessing the skeleton via entity->getMesh()->getSkeleton() will return a [master] instance of the skeleton that is probably not linked to any entity. any attempt to do a

Code: Select all

entity->getMesh()->getSkeleton()->getBone(i)->setManuallyControlled() 
will get you nowhere.

Instead, use

Code: Select all

entity->getSkeleton()->getBone(i)->setManuallyControlled()
to access the private skeleton of each entity and manipulate its bones.
rmmt
Gnoblar
Posts: 23
Joined: Sun Apr 03, 2005 7:14 am
Location: Philippines
Contact:

Post by rmmt »

Hello guys;

I have another question. Can we manually tell a bone or a set of bones to do a certain animation? This way, for example, I can have 1 mesh for a person, and have a "run animation" and an "arms up (but standing still) animation", then, if I wanted to make the character run while putting their arms up, I'll call each bone that I want to play the arms up animation.

Ex.:

1. make the char run
2. call the upperback, upper part of both arms, upper part of both lower arms, hand, fingers to play the "arms up (but standing still) animation".

If it's not possible with the current release, will it be possible with Dagon?
Ramon Miguel M. Tayag
rmmt
Gnoblar
Posts: 23
Joined: Sun Apr 03, 2005 7:14 am
Location: Philippines
Contact:

Post by rmmt »

anyone? :)
Ramon Miguel M. Tayag
User avatar
Kencho
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 4011
Joined: Fri Sep 19, 2003 6:28 pm
Location: Burgos, Spain
x 2
Contact:

Post by Kencho »

It's possible since more than a year at least. You define your animations for the upper body, and the ones for the loewr body. Then just use both of them (animation blending). If each bone is animated no more than one time, you'll have no problem.

Indeed, something similar could be done to make a character track positions (for instance, the character looking forwards, but pointing with his gun to a moving object -much a la Dante and his guns in Devil May Cry)
Image
rmmt
Gnoblar
Posts: 23
Joined: Sun Apr 03, 2005 7:14 am
Location: Philippines
Contact:

Post by rmmt »

cool, thanks :) will surely look into it!
Ramon Miguel M. Tayag
sabahmoura
Gnoblar
Posts: 3
Joined: Thu Dec 15, 2005 10:05 pm

Post by sabahmoura »

Hi! First, I am a newbie!

So... I would like to know where I should put this codes!

Code: Select all

        Entity *ent = mSceneMgr->createEntity("robot", "robot.mesh");

        Mesh* m = ent->getMesh();
        Skeleton* skel = m->getSkeleton();
        Animation* anim = skel->getAnimation("Walk");       
        manuallyControlledBone = skel->getBone("Joint10");
        manuallyControlledBone->setManuallyControlled(true);
        anim->destroyTrack(manuallyControlledBone->getHandle());

Code: Select all

        mAnimState->addTime(evt.timeSinceLastFrame);
        manuallyControlledBone->yaw(Degree(evt.timeSinceLastFrame*100));
Using ExampleApplication, the first block of code I put in the createScene method, right?! And the second block, in the frameStarted method, OK? But in the frameStarted method I can not reach the manuallyControlledBone. How could I solve this?

Thank you!!

:lol:
sabahmoura
Gnoblar
Posts: 3
Joined: Thu Dec 15, 2005 10:05 pm

Post by sabahmoura »

here is my entire code...

Code: Select all

 #include "ExampleApplication.h"

 #include <deque>
 using namespace std;

 class MoveDemoListener : public ExampleFrameListener
 {
 public:

     MoveDemoListener(RenderWindow* win, Camera* cam, SceneNode *sn, Entity *ent, const deque<Vector3> &walk)
         : ExampleFrameListener(win, cam, false, false)
     {
         // Set default values for variables
         mWalkList = walk;
         mWalkSpeed = 35.0f;
         mEntity = ent;
         mNode = sn;
         mDirection = Vector3::ZERO;

         // Attempt to setup the object to walk around.  If no points are
         // specified, set an idle animation.
         if ( nextLocation() )
         {
             // Set walking animation
             mAnimationState = mEntity->getAnimationState( "Walk" );
             mAnimationState->setLoop( true );
             mAnimationState->setEnabled( true );
         } // if
         else
         {
             // Set idle animation
             mAnimationState = mEntity->getAnimationState( "Idle" );
             mAnimationState->setLoop( true );
             mAnimationState->setEnabled( true );
         } // else

     } // MoveDemoListener


	 /* This function is called to start the object moving to the next position
	    in mWalkList.
	 */
     bool nextLocation( )
     {
         if ( mWalkList.empty() )
             return false;

         mDestination = mWalkList.front( );  // this gets the front of the deque
         mWalkList.pop_front( );             // this removes the front of the deque

         mDirection = mDestination - mNode->getPosition( );
         mDistance = mDirection.normalise( );

         // change facing
         Vector3 src = mNode->getOrientation( ) * Vector3::UNIT_X;
         if ( (1.0f + src.dotProduct( mDirection )) < 0.0001f )
             mNode->yaw( Degree(180) );
         else
         {
             Ogre::Quaternion quat = src.getRotationTo( mDirection );
             mNode->rotate( quat );
         } // else

         return true;
     } // nextLocation( )

     bool frameStarted(const FrameEvent &evt)
     {
         // Animate the object
         mAnimationState->addTime( evt.timeSinceLastFrame );
         
         //*******************************************************************
         manuallyControlledBone->yaw(Degree(evt.timeSinceLastFrame*100));
         //*******************************************************************

         if ( mDirection != Vector3::ZERO )
         {
             Real move = mWalkSpeed * evt.timeSinceLastFrame;
             mDistance -= move;

             // If we are very close, just jump to the point
             if (mDistance <= 0.0f)
             {
                 mNode->setPosition( mDestination );
                 mDirection = Vector3::ZERO;

                 if (! nextLocation( ) )
                 {
                     mAnimationState = mEntity->getAnimationState( "Idle" );
                     mAnimationState->setLoop( true );
                     mAnimationState->setEnabled( true );
                 } // if
             } // if

             // Otherwise, move some some
             else
             {
                 mNode->translate( mDirection * move );
             } // else
         } // if

         // Allow the parent class to execute
         return ExampleFrameListener::frameStarted(evt);
     }
 protected:
     Real mDistance;                  // The distance the object has left to travel
     Vector3 mDirection;              // The direction the object is moving
     Vector3 mDestination;            // The destination the object is moving towards
     Real mWalkSpeed;                 // The speed at which the object is moving

     AnimationState *mAnimationState; // The current animation state of the object

     Entity *mEntity;                 // The Entity we are animating
     SceneNode *mNode;                // The SceneNode that the Entity is attached to
     std::deque<Vector3> mWalkList;   // The list of points we are walking to

 };



 class MoveDemoApplication : public ExampleApplication
 {
 protected:
 public:
     MoveDemoApplication()
     {
     }

     ~MoveDemoApplication()
     {
     }
 protected:
     Entity *mEntity;                // The entity of the object we are animating
     SceneNode *mNode;               // The SceneNode of the object we are moving
     std::deque<Vector3> mWalkList;  // A deque containing the locations of points we wish to move to

     void createScene(void)
     {
         // Set the default lighting.
         mSceneMgr->setAmbientLight( ColourValue( 1.0f, 1.0f, 1.0f ) );

         // Create the entity
         mEntity = mSceneMgr->createEntity( "Robot", "robot.mesh" );

        //********************************************************************
        SkeletonInstance* skel = mEntity->getSkeleton();
        Bone *manuallyControlledBone = skel->getBone(9);
        manuallyControlledBone->setManuallyControlled(true);
        Animation* anim = skel->getAnimation("Walk");
        anim->destroyTrack(manuallyControlledBone->getHandle());
        manuallyControlledBone->yaw(Degree(90));
        //********************************************************************

         // Create the scene node
         mNode = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "RobotNode", Vector3( 0.0f, 0.0f, 25.0f ) );
         mNode->attachObject( mEntity );

         // Create the walking list
         mWalkList.push_back( Vector3( 550.0f,  0.0f,  50.0f  ) );

         // Create objects so we can see movement
         Entity *ent;
         SceneNode *node;

         ent = mSceneMgr->createEntity( "sphere1", "sphere.mesh" );
         node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Sphere1Node1", Vector3(  0.0f, -10.0f,  25.0f ) );
         node->attachObject( ent );
         node->setScale( 0.1f, 0.1f, 0.1f );

         ent = mSceneMgr->createEntity( "sphere2", "sphere.mesh" );
         node = mSceneMgr->getRootSceneNode( )->createChildSceneNode( "Sphere1Node2", Vector3( 550.0f, -10.0f,  50.0f ) );
         node->attachObject( ent );
         node->setScale( 0.1f, 0.1f, 0.1f );

         // Set the camera to look at our handywork
         mCamera->setPosition( 90.0f, 280.0f, 535.0f );
         mCamera->pitch( Degree(-30.0f) );
         mCamera->yaw( Degree(-15.0f) );
     }

     void createFrameListener(void)
     {
         mFrameListener= new MoveDemoListener(mWindow, mCamera, mNode, mEntity, mWalkList);
         mFrameListener->showDebugOverlay(true);
         mRoot->addFrameListener(mFrameListener);
     }

 };



 #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 #define WIN32_LEAN_AND_MEAN
 #include "windows.h"


 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
 #else
 int main(int argc, char **argv)
 #endif
 {
     // Create application object
     MoveDemoApplication app;

     try {
         app.go();
     } catch( Exception& e ) {
 #if OGRE_PLATFORM == PLATFORM_WIN32
         MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
 #else
         fprintf(stderr, "An exception has occured: %s\n",
                 e.getFullDescription().c_str());
 #endif
     }


     return 0;
 }
Thaks for any help!

:D
sabahmoura
Gnoblar
Posts: 3
Joined: Thu Dec 15, 2005 10:05 pm

Post by sabahmoura »

please... anybody?! I really need help!
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post by sinbad »

Using ExampleApplication, the first block of code I put in the createScene method, right?! And the second block, in the frameStarted method, OK? But in the frameStarted method I can not reach the manuallyControlledBone. How could I solve this?
You'll need to pass a pointer to the manually controlled bone to your listener then, in a similar way to how the camera and window are passed to it.
Julgood
Gnoblar
Posts: 6
Joined: Fri Jul 11, 2008 9:40 am

Post by Julgood »

Hello!

I have a small proble I've designed a mesh with its skeleton into blender.

The problem is that when I want to manually control bones into OGRE, it takes from origin the center of the body, its ok for some movements but if I want to rotate the left arm for example, it always take the center of the body for the origin of the rotation so the result is not what I want.

The thing I want is that the rotation I apply must take for origin the root of the bone. Are they any way to do that?

Thanks

Here is my code:

Code: Select all

		ent->getSkeleton()->getBone("L_Forearm")->setManuallyControlled(true);
		Bone *ForeArm = ent->getSkeleton()->getBone("L_Forearm");
		ForeArm->pitch(Degree(50));
Post Reply