Page 1 of 1

Animation Woes

Posted: Sun Jul 17, 2005 2:06 am
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

Posted: Sun Jul 17, 2005 4:41 am
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.

same thing

Posted: Sun Jul 17, 2005 4:15 pm
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?

Posted: Sun Jul 17, 2005 4:58 pm
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!

Posted: Sun Jul 17, 2005 5:04 pm
by Midnight
post more code..I have a feeling its not that code thats causing the problem.

Posted: Sun Jul 17, 2005 6:37 pm
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

Posted: Sun Jul 17, 2005 7:10 pm
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.
:?:

Posted: Mon Jul 18, 2005 12:46 am
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.

Posted: Mon Jul 18, 2005 3:27 am
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?

Posted: Mon Jul 18, 2005 8:35 am
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.

Posted: Mon Jul 18, 2005 10:28 pm
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.

Posted: Tue Jul 19, 2005 6:46 am
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

Posted: Wed Jul 20, 2005 4:14 am
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

Posted: Sun Jan 07, 2007 10:58 am
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