Visual studio - roaming ralph animation

Hello,

I have a problem when runnning the roaming ralph c++ demo in visual studio 2008. When i startup a new c++ project in VS and using the RR-demo source code, the roaming ralph run animation works the first time. But when i run the project a second time, ralph is walking around instead of running, and the stop pose is incorrect (flapping on one leg).
Cleaning the solution and project isn’t working.
I run VS in release-mode (F5) and i have included all path’s and library’s as specified in the manual, except the removal of the NDEBUG macro definition, because the definition isn’t set.

The only thing i have changed is on line 250 or something.

if(! is_moving) {

instead of

if(not is_moving){

Which can’t seem to be the problem to me.

Another thing is, when i run the exact same code (and models) under ubuntu 9.10 with eclipse, the animation works correctly each time.

Regards

Are you sure? I’m pretty sure NDEBUG is set by default in the project settings whenever you enable release mode. I can’t promise this is your problem, but having that set (and not realizing it) can cause weird things to happen.

David

The macro definitions can be found in:

Project properties -> C/C++ -> Preprocessor -> Preprocessor Definitions…?

If so, there isnt anything set then.

I actually just found the NDEBUG macro, didnt make a Win32 console application in VS at first, but just an empty one. So i did remove NDEBUG, only still having the same problem.

Regards

Hi. In c++ the auto_bind function seems to be screwed up. I did many tests and whenever you bind more then one animation, it screws up sooner or later.
I got so tired of it that I downloaded Netbeans and now I’m learning Python. Using Panda with C++ is, in my opinion, a huge pain in the x#$.
However, Python seems to be quite nice and has a lot of pro’s over C++.

Panda3D is written in C++. The Python part is just a wrapper that calls the C++ functions. So it is not possible that something works “better” in python that in C++ in Panda. When that happens it just means you are doing something wrong.

You see, for me it’s the opposite. Using Panda with python seems like a huge pain in the x-sharp-dollar symbol for me, but I just attribute that to the fact that I don’t know enough about Python. Just making sure people don’t get the wrong idea. The core of Panda is in c++, so whatever works in Python can work on C++ somehow. Peace.

I am in peace.
I’m just telling how it is for me. I stumbled way too many times over missing ‘wrapper’ functions.
I agree that c++ should be the language to use Panda, but it is not very well documented on the c++ side, and I found myself going throught the panda source over and over again simply to find out how something should be initialized.

On the autobind function: I am using the method used in the roaming ralph c++ version and it is NOT working.
Maybe it should be used differently, but if you simply search on the forum for c++ users having problems with animations, you’ll see that non of the ‘my animation is not running correcty’ threads (in the way I discribed) are solved.
I would love to go back to c++, so if anyone can solve the problem I would love that.

I use visual studio 2008 as well. Might have something to do with it.

I totally agree, there’s much to be done on the C++ on the side of documentation and samples. I don’t know about the ralph sample though, maybe somebody else can help you.

Yeah, I think its random behavior, I experienced it too. I don’t remember which solution I found for myself - but I looked in the ShowBase source code to see how it binds separate animations.
I think you have to use the AnimControl interface to find the animations. Not sure though - I haven’t done Panda games in C++ in a while.

Lol, I have spend so much time on it and now something just crossed my mind.
This is what fixes the animation error:
When you auto_bind AGAIN everytime you attach a new animation to the Parent nodepath, it works !
Just tried it with adding 26 animations.

Sigh…

In the Roaming ralph c++ example:

  win_ptr->load_model(ralph,"models/ralph-walk.egg.pz");
  win_ptr->load_model(ralph,"models/ralph-run.egg.pz");
  auto_bind(ralph.node(), ralph_anims, PartGroup::HMF_ok_part_extra | PartGroup::HMF_ok_anim_extra | PartGroup::HMF_ok_wrong_root_name);

Should be:

  win_ptr->load_model(ralph,"models/ralph-walk.egg.pz");
  auto_bind(ralph.node(), ralph_anims, PartGroup::HMF_ok_part_extra | PartGroup::HMF_ok_anim_extra | PartGroup::HMF_ok_wrong_root_name);

  win_ptr->load_model(ralph,"models/ralph-run.egg.pz");
  auto_bind(ralph.node(), ralph_anims, PartGroup::HMF_ok_part_extra | PartGroup::HMF_ok_anim_extra | PartGroup::HMF_ok_wrong_root_name);

Note: I did not check yet, if this method adds bad behavior like reserving too much memory and so on. I’ll get back to that

Ah, smart! That should be a fine solution, too. :slight_smile:

Hmm. It seems it isn’t such a good idea after all.
Check this dump I produced using

string AddAnimation(WindowFramework *window,NodePath parent,AnimControlCollection &anims,string AnimationFilename)
{
	window->load_model(parent,AnimationFilename);	
	auto_bind(parent.node(), anims,PartGroup::HMF_ok_part_extra | PartGroup::HMF_ok_anim_extra | PartGroup::HMF_ok_wrong_root_name);

	int CurrentAnim=anims.get_num_anims()-1;	// subtract 1; zero based index
	int AmountOfFrames=anims.get_anim(CurrentAnim)->get_num_frames();
	string AnimName=anims.get_anim_name(CurrentAnim);

	printf("Added animation [%s],wich contains %d frames.\n",AnimName.c_str(),AmountOfFrames);
	printf("The amount of animations in the AnimControlCollection is now %d.\n",CurrentAnim);

	return(anims.get_anim_name(CurrentAnim) ); // return generated anim name ( character.x )
}

and

map <int,string> Animation;
int CurrentAnimation=0;

#define HEADING_N	0
#define HEADING_NE	1
#define HEADING_E	2
#define HEADING_SE	3
#define HEADING_S	4
#define HEADING_SW	5
#define HEADING_W	6
#define HEADING_NW	7
Animation[CurrentAnimation++]=AddAnimation(win_ptr,ralph,ralph_anims,"players/Animations/Walking/WalkEasy_N.egg");
Animation[CurrentAnimation++]=AddAnimation(win_ptr,ralph,ralph_anims,"players/Animations/Walking/WalkEasy_NE.egg");
Animation[CurrentAnimation++]=AddAnimation(win_ptr,ralph,ralph_anims,"players/Animations/Walking/WalkEasy_E.egg");
Animation[CurrentAnimation++]=AddAnimation(win_ptr,ralph,ralph_anims,"players/Animations/Walking/WalkEasy_SE.egg");
Animation[CurrentAnimation++]=AddAnimation(win_ptr,ralph,ralph_anims,"players/Animations/Walking/WalkEasy_S.egg");
Animation[CurrentAnimation++]=AddAnimation(win_ptr,ralph,ralph_anims,"players/Animations/Walking/WalkEasy_SW.egg");
Animation[CurrentAnimation++]=AddAnimation(win_ptr,ralph,ralph_anims,"players/Animations/Walking/WalkEasy_W.egg");
Animation[CurrentAnimation++]=AddAnimation(win_ptr,ralph,ralph_anims,"players/Animations/Walking/WalkEasy_NW.egg");

Dump:

Added animation [character],wich contains 32 frames.
The amount of animations in the AnimControlCollection is now 0.
Added animation [character.2],wich contains 32 frames.
The amount of animations in the AnimControlCollection is now 2.
Added animation [character.5],wich contains 32 frames.
The amount of animations in the AnimControlCollection is now 5.
Added animation [character.9],wich contains 29 frames.
The amount of animations in the AnimControlCollection is now 9.
Added animation [character.14],wich contains 29 frames.
The amount of animations in the AnimControlCollection is now 14.
Added animation [character.20],wich contains 29 frames.
The amount of animations in the AnimControlCollection is now 20.
Added animation [character.27],wich contains 29 frames.
The amount of animations in the AnimControlCollection is now 27.
Added animation [character.35],wich contains 29 frames.
The amount of animations in the AnimControlCollection is now 35.

Press any key to continue . . .

So, instead of adding only the new animation, it adds the previous ones PLUS the new one.
Nice way to grow a list, I must say

This needs more investigation. To be continued. :confused:

Okay, I came up with a better fix.
Turns out that autobind seems to mess up anim names.
Don’t know where that goes wrong and frankly I don’t care :wink:
This is what works for me:

string AddAnimToControlCollection(WindowFramework *window,AnimControlCollection *Collection,string AnimationFilename)
{
	// Create a temporary AnimControlCollection to store the animation in. 
	AnimControlCollection CurrentAnim;

	// Just parent it to render
	NodePath parent=window->get_render();

	// Load the animation and attach it to the parent
	window->load_model(parent,AnimationFilename);   
	auto_bind(parent.node(), CurrentAnim, 0);

	// Get the pointer to the created AnimControl
	PT(AnimControl) NewAnim=CurrentAnim.get_anim(0);

	// Set up the name of the animation based on the amount of already added animations
	char AnimationName[100];
	sprintf(AnimationName,"character.%d",Collection->get_num_anims());

	// If this is the first animation, there is no .x
	if(Collection->get_num_anims()==0)sprintf(AnimationName,"character");

	NewAnim->set_name(AnimationName);

	// Store the animation into our collection
	Collection->store_anim(NewAnim,AnimationName);

	int CurrentAnimation=Collection->get_num_anims()-1;

	// Set names
	Collection->get_anim(CurrentAnimation)->set_name(AnimationName);
    Collection->get_anim(CurrentAnimation)->get_anim()->set_name(AnimationName);
	
	// Clean up (not sure this is Necessary)
	CurrentAnim.clear_anims();

	// return generated anim name ( character.x )
	return(AnimationName); 
}

And:

map <int,string> Animation;
int CurrentAnimation=0;

#define HEADING_N   0
#define HEADING_NE   1
#define HEADING_E   2
#define HEADING_SE   3
#define HEADING_S   4
#define HEADING_SW   5
#define HEADING_W   6
#define HEADING_NW   7

Animation[CurrentAnimation++]=AddAnimToControlCollection(win_ptr,&ralph_anims,"players/Animations/Walking/a_WalkEasy_N.egg");
Animation[CurrentAnimation++]=AddAnimToControlCollection(win_ptr,&ralph_anims,"players/Animations/Walking/a_WalkEasy_NE.egg");
Animation[CurrentAnimation++]=AddAnimToControlCollection(win_ptr,&ralph_anims,"players/Animations/Walking/a_WalkEasy_E.egg");
Animation[CurrentAnimation++]=AddAnimToControlCollection(win_ptr,&ralph_anims,"players/Animations/Walking/a_WalkEasy_SE.egg");
Animation[CurrentAnimation++]=AddAnimToControlCollection(win_ptr,&ralph_anims,"players/Animations/Walking/a_WalkEasy_S.egg");
Animation[CurrentAnimation++]=AddAnimToControlCollection(win_ptr,&ralph_anims,"players/Animations/Walking/a_WalkEasy_SW.egg");
Animation[CurrentAnimation++]=AddAnimToControlCollection(win_ptr,&ralph_anims,"players/Animations/Walking/a_WalkEasy_W.egg");
Animation[CurrentAnimation++]=AddAnimToControlCollection(win_ptr,&ralph_anims,"players/Animations/Walking/a_WalkEasy_NW.egg");
auto_bind(ralph.node(), ralph_anims,0);

ralph_anims.stop_all();
ralph_anims.loop(Animation[HEADING_NE],true);

To answer the original poster:

string Walking=AddAnimToControlCollection(win_ptr,&ralph_anims,"models/ralph-walk.egg.pz");

string Running=AddAnimToControlCollection(win_ptr,&ralph_anims,"models/ralph-run.egg.pz");

auto_bind(ralph.node(), ralph_anims,0);

// Now you can use for example:
ralph_anims.loop(Walking,true);