custom animation file importer.

Yeah, I could store the matrices somewhere when loading a mesh and set them again as animation matrices, in an example script. You’re saying if the matrices are read incorrectly, then it will be noticeable then?

OK, makes sense.

I think I should have been more clear, it’s not a format we invented for our game, we are making a “improved replacement engine” for an existing game that has it’s own game formats. So we can’t really make a new animation, until we make a custom importer/exporter for a 3d modeller, but that would also suffer the problems the panda3d importer has currently.

Certainly that will cause very noticeable destruction of the animation. But many different errors would cause a similar destruction, so I don’t know that we can conclude this is the source of the problem yet.

So you have a double problem: you have to completely understand the animation format used by this existing game, and you have to completely understand the animation format used by Panda.

I can’t help you much with the former, but to understand the animation format used by Panda I suggest constructing a simple model and animation file, for instance in Blender, and examining the data directly, and/or manipulating the data in Python to see what effect it has.

David

OK, i will test it

I’m pretty sure we understand the former completely. I got the specs of the format from someone who made an animation viewer for that format which worked perfectly (he did it in plain OpenGL).
Theres nothing special in the format, just absolute (uninverted) transform matrices, and by absolute I mean relative to the root, no parent bones at all.

Also, I don’t think the problem is with the animation format, but with the rigged mesh format. I rendered the bones as points and the animations looked perfectly fine. I’m thinking the problem is me setting the bone matrices (not animation matrices) incorrectly or setting the weigths/indexes incorrectly.

BTW, are there any functions for setting the matrices directly and not extracting the pos, hpr and scale separately? that would speed it a bit.

OK, i will test it

I’m pretty sure we understand the former completely. I got the specs of the format from someone who made an animation viewer for that format which worked perfectly (he did it in plain OpenGL).
Theres nothing special in the format, just absolute (uninverted) transform matrices, and by absolute I mean relative to the root, no parent bones at all.

Also, I don’t think the problem is with the animation format, but with the rigged mesh format. I rendered the bones as points and the animations looked perfectly fine. I’m thinking the problem is me setting the bone matrices (not animation matrices) incorrectly or setting the weigths/indexes incorrectly.

BTW, are there any functions for setting the matrices directly and not extracting the pos, hpr and scale separately? that would speed it a bit.

There are convenience functions like this on the egg structures that populate an egg file with animation data, but not on the low-level Panda structures that directly control the animation.

David

I thought egg is just a format that gets converted to Panda data types when imported. I have little experience in this, so maybe I just don’t “get” the point.

Anyway, then if I apply the pos, hpr and scale extracted from the matrix… wouldn’t it change the appearence of the actor? I mean if the animations are relative to the rest pose.

I could always send some example script/files.

It is, but there is also a series of API calls within Panda that can be used to populate an egg file, beginning with EggData and related structures. If you use these API calls, there are convenience functions for building an anim bundle with a matrix instead of component wise; but these functions simply decompose the matrix and send it the components, which is not difficult to do anyway.

I’m not sure what you mean here. The animations are not relative to the rest pose in this sense; they are designed to replace the rest pose transform, not add to it, so you might say they are relative to the identity matrix. The bottom line is that if, and only if, an animation frame contains the same transform as the rest pose transform, then the joint will be held in its original rest position.

David

ok, animations are not relative to rest pose, got it.

I haven’t had time to try your suggestion of setting the bone matrices as animation matrices yet.

but heres a screenshot of what i have so far:
img535.imageshack.us/i/65386749.png/
on the left side a sitting animation is played

heres without the bones rendered:
img33.imageshack.us/i/0454285644433.jpg/

doesnt really look like weight issue, more like wrong rotation of the bones (the positions are perfect). can you guess something from the images?

I agree, it doesn’t look like a weight issue. I think the transform you are feeding is just wrong. I’m not convinced that the positions are perfect from the pictures.

David

OK, I’ll post some animations then.

The green dots are the bones.

punch:
postimage.org/image/jkgit23j/

idle:
postimage.org/image/cofegg13/

comparing with the in-game animations, I can say that at least the positions are perfect (scales are always 1.0).

and here’s restpose:
postimage.org/image/ifhde2vt/

I think this is something that if you do right/wrong either looks as it should, or looks completely wrong.

Anyway, the guy who made the viewer in openGL said he multiplied the rest pose matrices with the animation matrices and multiplied with the weights to get the new vertex positions each frame. I don’t know about those low level stuff, but does that mean that the game format has the animation matrices relative to rest pose matrices, unlike Panda? And if so, is there an easy way to tell panda to behave like that? (sure hope it isn’t though).
But that wouldnt make sense as positions seem correct.

Sure does sound that way to me too.

No, but you can pre-transform the animation to pre-multiply the rest transform into each frame.

David

But wouldn’t the positions be wrong too in that case?

Anyway, if its true, how would I go around doing that?
Multiply (multiply?) values gotten from

decomposeMatrix(characterJoint.getTransform())

with the values in the animation matrices?

BTW, what’s getNetTransform()? I understand getLocalTransform() is used when you have parent bone hierarchy and want to get transforms relative to parent joints.

Yes they would, unless the rest pose didn’t have any translation information, which would be weird. But the bottom line is, you have to precisely duplicate in Panda whatever is being done in your original animation system. If the original animation system implicitly multiplies the rest transform, then you need to make your Panda importer do that too.

If you’re not sure whether the original animation system does this or not, it would be best to find that out first, but if you can’t, then you have to experiment and try it both ways in panda. If it almost seems to work one way, that doesn’t necessarily mean you’re close.

Aren’t you creating the animation tables? And didn’t you create the joint table and populate it with the rest transform? So you have the information you need before you started; you don’t have to query this information from Panda. Compose the rest transform that you used to populate the joint table with the animation transform for each frame that you used to populate the animation table. Isn’t that easy to do?

To answer your specific question about querying it from Panda, though, I think you’re confused. characterJoint.getTransform() returns the local transform of the joint reflecting the animation already playing on it. That is to say, it is the values in the animation matrices, for the current frame. By the time you have an animation loaded and playing on a characterJoint, though, it’s too late to modify the animation matrices; you need to modify these at the time you construct the animation tables, not at the time you’re playing them back.

In any case, you certainly wouldn’t decompose the matrix first. Transforms don’t compose componentwise; the whole point of a matrix is to make the concept of “composition” trivial (it’s just a matrix multiply).

The method joint.getTransform() returns the joint’s local transform, relative to its parent. This is the transform as specified by the current frame of the animation, or the rest transform if the model is not currently animated. The method joint.getNetTransform() returns the composition of all of the joint’s inherited transforms, up to the root of the joint hierarchy; thus, it is the “net” transform or global transform of the joint (or, more precisely, the transform in the space of the root of the joint hierarchy). There is no method joint.getLocalTransform(), but maybe you’re thinking of getLocalTransforms(), which returns the list of nodes that will have the local transform automatically applied to them each frame.

David

It can’t be the case, you can see it in the screenshot I posted above. The rest positions are correct.
But positions for animations seem perfect too, you can see it in the gifs I posted. So… maybe this isnt the case.

well, I just have a loadModel function which returns an Actor. I don’t really have the variables holding that data in the global scope, it would be rewritten anyway if I loaded another model file.

so… what method can I use then?

You said in your first post:

So, can’t you edit that custom mesh and animation file importer to modify the animation tables before they generate the AnimBundleNode? Once you have an Actor, it’s too late.

I’m talking about preprocessing animations before they’re created, not modifying already loaded animations. So of course there aren’t any Panda methods that are appropriate for this, because we’re talking about code that is outside of Panda (i.e. your code).

David

Hm, I think theres a confusion here.

You said its possible that the animation format’s matrices are relative to rest matrices (model format’s), so when creating the animbundlenode, when assigning values to AnimChannelMatrixXfmTables, I’ll have to multiply the values with the rest matrix values. How can I get the rest matrix values? Ive loaded it with another function and the variables can’t be accessed anymore, theyre removed. And maybe Ive already called the function several times to load other models. So i would need to get them from the Actor…
It’s not like I’m loading the model and animation together so they have access to each other’s data.

You can get the rest transform from an existing joint in a loaded Actor with joint.getDefaultValue().

You’re not? But the two files are inextricably linked. Even if you don’t want to load them both at the same time, you should consider maintaining some global data that’s accessible to both of them.

David

Hm, could work. Will try now.
I’m going to multiply it with the animation matrices and get the data from that matrix, as I’ve already inverted it when creating the bones.

It’s like any other game, you have few model files and few hundred animation files. Loading them all is not possible.
I think storing global data for every single model we load would be inefficient. It would be easy to just pass the Actor to the animbundlenode creator function, so it would know which model’s rest transforms it needs.
Or since there are only two kinds of skeleton structures used in the game anyway, just hardcode them.

So Panda’s animation system doesnt have the animation transforms relative to the rest poses? because I browsed some pages on how skinning works and they all say you need to multiply the inverse of the trasform matrix (joint matrix) with the animation matrix. It seems like it’s the case for x files too (I think).

oh pshaw! I just set the hpr in prh order.
It’s not the case, the formats work like egg files.
So it’s all working now.

Could I ask some technical questions about making a Blender importer here? The Blender forums are pertty passive when it comes down to this kinds of questions.

However, what you said doesnt seem to be very accurate either. I mean animation matrices not being relative to the rest pose joint matrices. Becuase I set an empty Mat4 on for each joint instead and everything was screwed up when running the animations.

There is a tiny bit of a problem though. Its nothing to do with the file, but panda. Basically, the generated Actor consists of multiple geoms. When I load an animation and get close to the model, some pieces like the head disappear. This is not present without animations. It looks like a bounding box issue. What am I doing wrong?

I’m glad you found the right combination. :slight_smile:

Sounds like a disagreement on the meaning of our terms. If you set an identity Mat4, it will of course be screwed up if the animation matrices are not relative, because you have completely replaced the transform with identity. If the animation matrices are relative, however, then identity Mat4 would have no effect, because that would mean no change to the rest transform. What does “relative” mean to you?

This happens because Panda’s animation system doesn’t recompute the bounding volumes of the individual pieces as they animate. The easiest workaround is to pass setFinal = True to the Actor constructor (or explicitly call setFinal(True) on the Actor’s top node). This tells the bounding-volume system to treat the Actor’s top node as the authoritative bounding volume for all geometry at that node and below, so it will no longer clip out pieces.

If the Actor’s animation moves it significantly from its own origin, you may need to further specify a explicit bounding volume large enough to contain the actor and all of its animation, like this:

actor.node().setFinal(True)
actor.node().setBounds(BoundingSphere((0,0,0), 100))

David