Animation Woes

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
luckymutt
Posts: 453
Joined: Sun Mar 06, 2005 11:56 pm
Location: C-Ville

Animation Woes

Post by luckymutt »

Alright, I've been searching about the forums and can't quite put together triggering an animation.
I have an *.X file loaded with an animation that I want to call when the camera is a certain disance away.
setting the difference from camera to node is no problem, but I can't seem to get the animation to kick in.
If I do:

Code: Select all

core::vector3df cameraPosition = camera->getPosition(); 
f32 distance = cameraPosition.getDistanceFrom(node->getPosition());

	while(device->run())
	{

if (distance < 100.0f)
{
        node->setFrameLoop(0, 50);
}
else
{
    node->setFrameLoop(0, 0);
}
   
		driver->beginScene(true, true, video::SColor(255,113,113,133));
		smgr->drawAll();
  
		driver->endScene();
   }
	device->drop();
	return 0;
}
...then the animation does not play at all, no matter the distance between camera and node.
If I remove the:

Code: Select all

else
{
    node->setFrameLoop(0, 0);
}
...then the animation plays continuously, nomatter what the distnces are.

Any clue?
Need any additional info to figure this out?

From searching the forums, I have also tried something like:

Code: Select all

for (int i = 0; mesh->getFrameNr() < mesh->getFrameCount(); i++) 
{ 
mesh->setCurrentFrame(i); 
}
but alas, all to no avail.
I want to have the animation play one time when the distance is 100.0f(or whatever), but I can't even seem to get it to trigger in any way.
I've looked over the API docs for IAnimatedMeshX and such but...well, I don't entirely "get it."

please help...with a snippet if possible.

Thanks
Irme
Posts: 55
Joined: Sat Jul 16, 2005 8:24 am

Post by Irme »

i *think* that if you set the animationspeed property to 0 instead of setting the frameloop property, it should stop it for you. and then turn the animation speed back to the normal value to start it up again.
luckymutt
Posts: 453
Joined: Sun Mar 06, 2005 11:56 pm
Location: C-Ville

same thing

Post by luckymutt »

Thanks, for the reply, but I'm getting the same.
Changing it to:

Code: Select all

	while(device->run())
	{
if (distance < 100.0f)
{
        node->setAnimationSpeed(1000);
}
else
{
    node->setAnimationSpeed(0);
}
...there is still no triggering going on. With the "else" statement, there is no animation no matter distance/collision.
Without the "else" statement, the animation continues no matter for distance/collision.

Anybody else know how this would work?
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

My best guess at this point in time is...


if(blah)
{
blah
}
else IF(blah)
{
blah
}


OR


while(device->run())
{
if (distance < 100.0f)
{
node->setAnimationSpeed(1000);
BREAK; or return..or whatever it takes.
}
else
{
node->setAnimationSpeed(0);
};<- even that works some times


I suggest making sure of the problem in guice I built a console and I simply set a console message for every action..even having it print the variables I throw around to be sure of where the problem is.

make sure all parts work individually before attempting to make them work simultaneously.

...I also suggest you make sure frames 0-50 don't already do the same thing as 0-0.. but I hope you aren't making that mistake.

at any rate with a simple console of some kind you can debug this untill it works.. just simply try writing the code a different way there is other ways of doing the same thing...try them!
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

post more code..I have a feeling its not that code thats causing the problem.
luckymutt
Posts: 453
Joined: Sun Mar 06, 2005 11:56 pm
Location: C-Ville

Post by luckymutt »

Thanks Midnight.
I tried adding the "break;" and "else if" as well as the ";" at the end of the else block, but to no avail.
I'll throw in some prints to the console when the distance is hit, but in the meantime, here's the whole thing:

Code: Select all

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
#pragma comment(lib, "Irrlicht.lib")

IrrlichtDevice* device = 0;

int main()
{

     	device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(1024, 768),
		16, false, false, false);
          
  	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();

    scene::IAnimatedMeshX* mesh = (scene::IAnimatedMeshX*)smgr->getMesh("media/Swing.X");
    scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); 
	
              scene::ITriangleSelector* selector = 0;
              node->setPosition(core::vector3df(0,0,0));
              selector = smgr->createOctTreeTriangleSelector(
              mesh->getMesh(0), node, 0);
              node->setTriangleSelector(selector);
              node->setFrameLoop(0, 50);
             
              selector->drop();

//wasd navigation 
   SKeyMap keyMap[8];

   keyMap[1].Action = EKA_MOVE_FORWARD;
   keyMap[1].KeyCode = KEY_KEY_W;

   keyMap[3].Action = EKA_MOVE_BACKWARD;
   keyMap[3].KeyCode = KEY_KEY_S;

   keyMap[5].Action = EKA_STRAFE_LEFT;
   keyMap[5].KeyCode = KEY_KEY_A;

   keyMap[7].Action = EKA_STRAFE_RIGHT;
   keyMap[7].KeyCode = KEY_KEY_D; 

 //   add FPS camera 
    scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, 40.0f, 40.0f, -1, keyMap, 8);
    camera->setPosition(core::vector3df(0,50,-300));

// collision detection 
  scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
                           selector, camera, core::vector3df(30,50,30),
                           core::vector3df(0,0,0),
                           core::vector3df(0,50,0));
            camera->addAnimator(anim);
            anim->drop();

node->setDebugDataVisible( true);                          
    
// disable mouse cursor       
	device->getCursorControl()->setVisible(false);

// Add a light 
	smgr->addLightSceneNode(0, core::vector3df(-60,100,-400),
		video::SColorf(1.0f,1.0f,1.0f,1.0f),
		600.0f);

	int lastFPS = -1;

while(device->run())
	{

core::vector3df cameraPosition = camera->getPosition(); 
f32 distance = cameraPosition.getDistanceFrom(node->getPosition());
if (distance < 100.0f)
{
        node->setAnimationSpeed(1000);
        break;
}

else if (distance > 100.0f)
{
    node->setAnimationSpeed(0);
};

 camera->updateAbsolutePosition();
 node->updateAbsolutePosition();
   
		driver->beginScene(true, true, video::SColor(255,113,113,133));
		smgr->drawAll();
  
		driver->endScene();
   }
	device->drop();
	return 0;
}
the file I'm loading is just a simple block (with bones, keyframes, etc.) that I'm using as a proxy until I get the real content created. It was created in 3dsMax with 50 frames of animation, used PandaX to export it, opened it in the DXSDK meshViewer, saved it from there as a *.x file, opened it in Irrlichts MeshViewer, and all is well. The animation works fine until I try and control it.

Thanks for having a look. I'll mention anything from the console.

EDIT::::
ok I saw something...the
core::vector3df cameraPosition = camera->getPosition();
f32 distance = cameraPosition.getDistanceFrom(node->getPosition());
lines were not in the while(device->run) bit. That made a difference.
I had it there the other day and it didn't work, now it does, so I'm gonna guess it was the "else if()" that did it.
Now as I aproach the scene node, it does indeed trigger the animation, and it keeps spinning about, and when I back away from that distance, it stops.
Now, how would i get it to do just the 50 frames once and stop?I tried using if(distance = 100.0f)
and
else if(distance != 100.0f)
but the animation is looping from the start and continues
luckymutt
Posts: 453
Joined: Sun Mar 06, 2005 11:56 pm
Location: C-Ville

Post by luckymutt »

Changing my if statement to:

Code: Select all

if (distance < 100.0f)
{
             printf("start animation here\n");
for (int i = 0; node->getFrameNr() < mesh->getFrameCount(); i++)
{ 
node->setCurrentFrame(i); 
}        
}
the program locks up when I hit the distance.
the message is printed to the console, but I lose mouse control and movement...not even alt+F4 will make it quit.
:?:
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

well don't do that then.. :shock:


what about if(distance > 100)

??

= means something = something.

== means if this is equal to
Now, how would i get it to do just the 50 frames once and stop?I tried using if(distance = 100.0f)

if(distance == 100.0f)


I'm not that experienced with 3d in Irrlicht as much as 2d but can you turn the animloop into a variable?

also try returning both false within another loop like a mouse button or something.

if(node)
{
if(distance == 100)
{1-50}
else if (distance != 100 && distance > 100)
{0-0}
return false;
}

you can also try setting the loops to buttons to check if loop 0-0 even works at all.
luckymutt
Posts: 453
Joined: Sun Mar 06, 2005 11:56 pm
Location: C-Ville

Post by luckymutt »

No luck.
In fact, whenever I try:
if(distance == 100.0f)
I wind up getting really strange things happening with mouse and movement. Mouse won't move, and it will continue going forward/backward after releasing the key.
I also tried:
in the else if(distance != 100.0f)
and I even changed their places:
if (distance !=100.0f)
{ set animation speed (0) }
else if (distance == 100.0f)
{ setAnimationSpeed(100) }
but no difference.
So, as it is, I can get the animation to trip with:

Code: Select all

if (distance < 100.0f) 
{ 
   node->setAnimationSpeed(100);
}
else if (distance > 100.0f)
{
       node->setAnimationSpeed(0);
}
which should be good enough, so long as i can tell it to stop after it hits frame 50.
i tried

Code: Select all

 f32 rate = node->getFrameNr();
if (rate > 49)
  {
   node->setAnimationSpeed(0);
  }
but this has no effect.

Anybody get any ideas?
ondrew
Posts: 20
Joined: Fri Oct 03, 2003 2:24 pm
Location: Czech Republic

Post by ondrew »

I think your code works correct, but you set the animation to the first frame only, so you don't see anything.

I use blender and jox's exporter and for some unknown reason I have to multiply the number of the endframe by 150. Seems to work, every model needs a little bit tweaking. Just increase the number until it stops working.
luckymutt
Posts: 453
Joined: Sun Mar 06, 2005 11:56 pm
Location: C-Ville

Post by luckymutt »

No, man, the animation is running fine, it just won't stop after playing once.
What I was trying to do was have it get the current frame, and if it is greater than 49 (the last frame of animation is 50) then it would set the speed to 0, hoping it would stop on frame 50.
But it isn't working.

Has no one else tried to get an animation to play only once and not reset?

I'm gonna go bang my head on a desk for a little while.

thanks for everyone and anyone's thoughts on this.
ondrew
Posts: 20
Joined: Fri Oct 03, 2003 2:24 pm
Location: Czech Republic

Post by ondrew »

Sorry, I didn't understand it the first time. Anyway I use both single and continuous repeating of animations and apart from multipling the end frame, it works correctly for me.

My next theory is, that you don't set the loop mode correctly. At least I don't see it anywhere in your source.
http://irrlicht.sourceforge.net/docu/cl ... de.html#a8

You should start the animation by executing these commands:

Code: Select all

setFrameLoop(0, 50);
setAnimationSpeed(100);
setLoopMode(false); 
setAnimationCallback(&callback); // if you use one
luckymutt
Posts: 453
Joined: Sun Mar 06, 2005 11:56 pm
Location: C-Ville

Post by luckymutt »

THANKS...that seemd to do it.
(still learning how to read the API docs...programming newbie here)

The only thing I can't quite figuure is setting the speed of the animation.
While reading over the docs, it says the number is the number of frames per second.
Well, with my animation having 50 frames, and the:

setAnimationSpeed(100);

it plays the animation pretty quick...no, very quick.

So I started experimenting with different values, and I found that ANY value I put in there, the animation would play at that same fast speed, unless the value was set to 1
With setAnimationSpeed(1); It clicked by, frame by frame. One frame per second, as you would expect.
But even setting this to setAnimationSpeed(2) it goes right back to playing it at the really fast speed.

I'd like to get this to play at ~2 seconds.
Is there something wrong with the way I'm doing this?
Or should I redo the animation and set it for more/less frames?

thanks again to all
Stainless
Posts: 7
Joined: Sat Jan 06, 2007 1:54 pm

Post by Stainless »

Don't forget that animations in Irrlicht are interpolated by a factor of 8

so if you want to use ten frames you need to setframeloop from 0-80
Post Reply