custom animation file importer.

Im making a custom mesh and animation file importer inside panda which generates and actor and animbundlenode respectively.
I have the mesh importer working, but I cant get the animation file importer working properly.

The thing is in the file the joints are not relative to their parent, like in Panda, but relative to the pivot point (root). So i dont set parent bones when creating the joints and xfm tables. Like i mentioned the mesh loads perfectly, and the joints are in their place, but when i load an animation, all the bones are repositioned in the center and there is no animation happening.
the animations in the file are stored in 4x4 matrices and I use this to get pos,loc,scale:

matrix = Mat4() # read from file

# get position
pos = matrix.getRow3(3)

# get rotation,scale,shear
rot = Vec3()
scale = Vec3()
shear = Vec3()
	
transform = decomposeMatrix(matrix.getUpper3(), scale, shear, rot)

i then pass the values to the AnimChannelMatrixXfmTables. so i make a new table for each bone:

animskeleton = AnimGroup(animbundle, '<animskeleton>')

#...

boneanim = AnimChannelMatrixXfmTable(animskeleton, str(jointnames[i]))

and set all the values i got previously to the tables.

I then make the animation node

animbundlenode = AnimBundleNode('animbundlenode', animbundle)
	
anim = NodePath(animbundlenode)

and pass it to the actor, but i get what i described: all joints are repositioned to the center, everything is scale up and I see no animation

Well, there’s a lot of complex things in the animation system. How can I help you debug your problem most effectively?

Have you tried turning on the notify debug output? You can set:

notify-level-chan spam
notify-level-char spam
notify-level-Actor debug

in your Config.prc file to get the most possible debug output from the animation system. Maybe this will give you some insight.

David

Hey, good suggestion.
When i set those notify levels the game crashed when loading an animation file with this messages:

:chan: Part character has a different set of children  than matching anim node:
:chan:   anim has <animskeleton>, not in part.
:chan:   part has <skeleton>, not in anim.
:chan(debug): binding neck to

BTW, what is AnimChannelScalarTable used for?

That crash is actually a bug in the debug statements, but it indicates that it was binding with the NULL anim, which just means to play no animation. So it appears that your animation hierarchy did not match your skeleton’s hierarchy.

Note that the name of each joint, and the number of children of each joint, must match precisely between skeleton and animation.

This is used to animate a slider. A slider is like a joint, but it only slides along one axis, typically from 0 to 1, instead of receiving a full 4x4 transform. It’s used to implement morphs.

David

I changed the AnimGroup name “” to the PartGroup name “” and it worked. I can’t say I totally understand what the name is needed for. But anyway, the animations are loading and playing nicely now although I have some issues with weights.

I also noticed that the rest rotations are kinda random, both in egg files and the format I’m using. It seems like the restpose rotations are not important and the animations are not relative to them. Is this the case?

The name “” is a required name for historical purposes; it serves no great purpose other than that all egg files have it.

Yes, animation tables are not relative to the rest pose. However, the model’s vertices are, so it may be important to chose a suitable rest pose that results in minimal distortions of the model’s vertices.

David

I’m not sure I understand what youre saying.
By transform do you also mean rotations?
Because by my limited knowledge the rotations can be random (90 or 180 degrees off).
Here is the default panda model in egg:
img689.imageshack.us/i/12454122542rgfe.jpg/

or is there something I don’t know about?

The y-to-z-up conversion introduces a 90-degree rotation on each joint. It’s not random; it’s consistent across the entire model (and it depends on the model, and the modeling package that created it).

But that rotation doesn’t really matter. The important thing is that the area of the polygons be about the same in the rest post as they tend to be in the animation–you don’t want the polygons folded in on themselves in the rest pose.

David

I don’t think I understand.

So you mean positions in rest pose matter if you want the model to look correct without having an animation on it, but rotations aren’t important either way because the transforms aren’t relative to the rest pose?

The Panda model was created in a Y-up coordinate space (if you look at the egg file, it begins with the line that specifies Y-up). Panda uses a Z-up coordinate space by default, so when you load the egg file it has to convert the model from Y-up to Z-up, which means rotating each joint 90 degrees. If the Panda model had been created in Z-up to begin with, or if you configured Panda to run in Y-up mode (for instance with “coordinate-system y-up” in your Config.prc file), this rotation wouldn’t be necessary.

No, the positions in rest pose have nothing to do with the way the model looks when no animation is on it (because “no animation” really means to put the rest pose on each joint).

I think you’re making too much a big deal out of it. The bottom line is, the rest transform doesn’t matter much.

David

I would love to get some more info on this. From the image I posted you can see that left hand bone matrices and right hand bone matrices are different by 180 degrees along Roll. And I’ve experienced a similar thing with other formats (90 or 180 degrees). I’m pretty sure the bones werent modelled in such a way in the first place.

hm, I’m confused, you say no but you then say rest pose is put on each joint. If rest pose is put on each joint then having all rest pose locations at (0,0,0) would affect on how the model looks, right?

“much”?

I know this isn’t very important but I just want to know how it works completely and also I have some visual issues which might be caused by this (I would know for sure after these things were cleared out).

I can assure you that they were. Whatever you see in Panda, that’s the way the model was constructed, with the exception of the 90-degree rotation on every joint that the y-up-to-z-up conversion causes. If you configure Panda temporarily to y-up mode, or hand-edit the egg file to change the Y-up at the top to Z-up, then you’ll see the model precisely as it was originally constructed.

No, because the vertices are set according to the rest pose transform. This means that whenever you load the rest pose transform on every joint, the vertices are placed in the position they have in the original model file. If you load a different transform on a join, then the vertices are transformed by the difference between the new transform and the original rest pose transform. That’s what the rest pose means: it is the transform required to return the vertices to their original position.

If you load the Actor and set all the transforms to identity, it will collapse the vertices into a puddle.

On the other hand, you can first hand-edit the egg file and put the identity transform on every rest pose. This is mathematically equivalent to transforming every joint by its own inverse. This will completely botch up the animation file, of course, unless you also transform the joints of the animation file by the same inverse transform. But now if you load the Actor and set all the transforms to identity, it will set the model into its neutral pose, because that’s what the rest transform means.

David

Sorry, I don’t really understand.

So the rest pose does matter and wrongly loaded rest rotations might cause wrong animations?

I want to know because I had the suspicion that I set the weights/bone indexes improperly, but it seems like when I visualise the bones, the ones that have different angle compared to the same bone on the other side (simmetrical human body) are the ones which are messed up.

It could be a weights issue though, because I tried rotating the bones with controlJoint() and the mesh deformed unusually, but it seemed okay when I rotated it around it’s own coordinate space ( joint.setHpr(joint, 0,90,0) )

The animation is dependent on the rest pose. If you change the rest pose without changing the animation the same way, you will break the animation. In that sense the rest pose matters.

It’s really quite simple: the rest pose defines the transform that is initially loaded on each joint. This is the transform that restores the model to its pose featured in the original egg file.

The animation defines the transform that replaces the rest transform for each joint, each frame. If the animation transform is the same as the rest transform, the model will hold its neutral pose. If the animation transform is any other transform, the model will hold some other pose.

Visualizing the bones isn’t likely to lead to insight, because the joint’s rotation may be contrary to your intuition. It doesn’t matter. As long as the animation’s rotation matches this, the animation will play correctly. In this sense, the rest pose doesn’t matter.

You can experiment with a single joint using controlJoint() as you describe; this might lead to a greater understanding of how it works. Observe what happens when you load the identity transform on a joint. Now observe what happens when you load the original rest transform on the joint. And also observe what happens when you load some of the transforms indicated in the animation file for that joint.

David

i understand what you are saying now, but I’m really not sure if that will help me undertsand the problem here. I could pm you an example with the script…

Try generating an animation that loads just the rest transform for every joint, as a starting point. If you can get that to work (and it results in the actor holding its original rest pose), then you can move on to generating an animation that does the same thing, but then rotates a single joint about a single axis.

If you can get that to work, and you have control over the particular axis that the joint rotates about, then you should understand the animation system enough to generate a full-body animation.

David

I’m not actually generating the animations on the fly, but loading them from a file, like the actor, if that’s what you mean.

The loaded Actor is perfectly fine (it is in the rest pose right?). Is that what you wanted to know?
I’m just saying by attaching a 3d mesh that looks like a bone in a 3d modeller to each joint, the rotations seem to be different by 90 or 180 on the left and right side of an symmetrical actor (this is also with egg files), like in the image posted. For example the right arm bone points up while the left arm bone points down.
The reason why I want to understand why it is like this is that it will allow me to know if the artifacts I have with weights are caused by me assigning the weights/indexes improperly or creating the bone matrices improperly.
Because I also notice that in egg files, I guess its normal, but i can’t be too sure.

Well, that’s good to know; but what I meant was whether it remains perfectly fine after you have loaded an animation that should not change anything. The purpose is to test whether you have a good understanding of what an animation that should not change anything looks like.

But maybe I don’t understand what you’re trying to do. Aren’t you talking about generating animations? Because if you’re just loading pre-generated animations that came out of the same animation package that produced the model, then none of this matters and you don’t need to know what direction the joints are facing.

That is, even if the joints on the right are rotated 180 degrees from the joints on the left, they will be rotated the same way in the matching animation file, so it balances out.

So, you’re replacing the entire model and animation loading pipeline? Maybe it would be easier to do this if you started with a much simpler model, for instance one with only one or two joints, instead of something like the panda model.

David

What if it doesnt? What does that mean?
BTW, you mean to have identification matrices for the animations?

Yes, that’s what I’m doing.
The reason I’m asking this is that I have a suspicion that the “wrong weights” when playing the animations could be caused by me reading the matrices from the files incorrectly. Because by my knowledge, even if the matrices are wrongly read, it wouldn’t affect the mesh as joints are created after the geoms in the script. Or am I wrong here and wrong matrices would be noticeable without animations, by just rendering the actor?

Another reason is that we’re also writing a Blender importer for that format and the bones are again different from side to side, so it’s not very usable. We are wondering if “fixing” the weird rotations during import and then exporting those bones from Blender, etc. will make the new/modified character usable with the existing animations.
Thats also the reason why I want to know why the exported bones in egg/other formats have “weird” rotations.

well, we’re just adding another format support to the game.

It would mean that you misunderstand how an animation file works. For instance:

No. That would be completely wrong. I mean an animation whose matrices exactly matches the rest pose matrices. That’s the kind of animation that doesn’t do anything.

Wrong matrices wouldn’t be noticeable until you apply animations. You don’t have to take my word for this: you can experiment with this by mangling the matrices by hand and seeing what happens.

Again, I suggest working with a much simpler animation file to gain a clearer understanding of the forces involved.

Wouldn’t it be much easier to write a converter from your new format into egg, and then load the converted egg file? After all, the whole purpose of the egg format is to be an easy-to-understand and easy-to-generate file format to describe Panda structures such as geometry and animation. It’s also designed to be forward-compatible to future versions of Panda, even if Panda reworks its animation system internally.

David