- June 12, 2009 at 1:18 pm #29822
Could someone please tell me what GetBoneWorldMatrix is doing? I can’t seem to make sense of it. I don’t understand why the transforms appear to go like this:
1) mesh’s world matrix at frame zero
2) inverse of the bone’s world matrix at frame zero
3) the bone’s world matrix at current frame
Seems like it should go the other direction, but either way I can’t seem to visualize or understand why frame zero is involved. And I have no idea what space anything is in. Is the bone a child of the mesh node? Why not just use GetWorldMatrix on the bone? Does the matrix palette hardward require a relative transform of sorts? If someone can help me out with this I’d appreciate it. My curiosity is killing me.
-GregJune 13, 2009 at 3:09 am #33129
Well maybe someone can just look at this and tell me what’s up. I’d really appreciate it.Code:void CPVRTModelPOD::GetBoneWorldMatrix(
const SPODNode &NodeMesh,
const SPODNode &NodeBone)
fFrame = m_pImpl->fFrame;
// Transform by object matrix
// Back transform bone from frame 0 position
PVRTMatrixMultiply(mOut, mOut, mTmp);
// The bone origin should now be at the origin
// Transform bone into frame fFrame position
PVRTMatrixMultiply(mOut, mOut, mTmp);
}June 14, 2009 at 4:44 pm #33130
After thinking about it, this must have something to do with bringing
the mesh verts from the bind pose to the new bone position. I’m still
confused as to why the mesh’s world matrix is applied first instead of
last. Please someone respond. I feel like I’m talking to myself.July 7, 2009 at 10:28 am #33131Exports are done at a certain frame number; this makes rendering the object look correct even if bones are not applied, i.e. you see the bind pose.All transforms are from “node”/model space to world space.All meshes are in model space.Therefore we must:1) transform mesh into world space2) back-transform from world-space into “bone space”/the bone’s model space at frame 03) transform into bone’s world-space position at the required frame numberRegards,Aaron.July 8, 2009 at 5:53 am #33132
Thanks for responding. I understand more now, but I’m still a bit confused. Why frame 0? I imagined that you’d need to bring the mesh verts from the bind pose. Does the export process bake the mesh out to its frame 0 position?
-GregJuly 17, 2009 at 10:46 pm #33133
I asked this in the 1.1 forum but here goes,
On this note, what is the best way to procedurally animate a skinned mesh via SPNode bones? There seems to be no facility for this, the spAnimPosition, etc., are never null even when I have animation unchecked in the 3dsmax exporter, so therefore the NonCached versions of GetWorldMatrix are never used and spPosition, spRotation are ignored and frame zero is always referenced.
We have a rigged and skinned vehicle in which I need to manually transform the bones to match the physics solution (Wheel positions, etc.,) and I am looking for the most efficient way to do this and still use the matrix palette skinning for deformation.
RBGamesJuly 18, 2009 at 9:53 pm #33134
Don’t distract Aaron, he’s thinking about responding to my question. 🙂
I’m curious, are you using the skinning to show damage, or is it a cartoon vehicle maybe?
If you’re trying to do what I think you’re trying to do, procedurally simulate suspension, I’d break the model up into pieces that I could move around by changing the transform on the parent nodes of each piece. That way I wouldn’t have to worry about confusing system internals. You’d have to reassemble manually all the pieces into a whole vehicle again, and for that you might want to export some sort of rigid skeleton with attach points (if you plan on reusing parts on different vehicles) or maybe you could just use their initial world space positions. Doing this you should still be able to animate a denting door or a wobbly wheel.
But if you’re planning on doing some inverse kinematics with the bones then assuming you’ve got a system for inverse kinematics worked out you’ll have to understand the sdk’s bone animation system and just change the bone transforms. And look at the code to make sure what you’re doing isn’t hitting their matrix cache. That should be the easy part, the hard part I think would be the inverse kinematics.
I would think about maybe faking IK with moving around rigid parts. It might be less intensive than inverse kinematics. For example you could figure out roughly the slope of your wheel axels by sampling your terrain heightmap under the wheels. That will give you a vector you can then normalize and use as a rotation transform to move your axes. After positioning each axes you could use the center of each axis to compute the orientation of your chasis. You could also soften abrupt changes in rotation by making the final chasis rotation a percentage of the previous and new rotation.
But idk, I should stop rambling because I’m not even sure what you’re doing exactly. 🙂
GregJuly 18, 2009 at 10:36 pm #33135
It’s an iPhone title, so, in order to minimize draw calls, the body, wheels and body-panels are skinned. This way, I can move the wheels, which stretches the shocks, even blow off the body panels and it is still one draw call, since it is one mesh and one texture and I’m just translating the bones.
It is a trick we have used in the past in order to minimize draw calls on all sorts of things. Since on the iphone you are generally trying to maintain < 30 draw calls in order to keep frame rate.
The vehicle is driven via bullet physics and already functions fine, I just needed to manually manipulate the bones for the wheels and axles now to match and there is no “good way” evident in the existing SDK.
RBGamesJuly 18, 2009 at 11:14 pm #33136
That’s interesting, I wouldn’t have realized that a vehicle would fit into one bone batch. There’s a no cache version of the GetWorldMatrix method. And I remember seeing them clear their matrix cache in code. But I’m not even sure the bone stuff uses the world matrix cache. So I guess I’m no help. I’m sure it could be done with some hackery, but I’d have to try and do it. You just need to update a bone transform right?
You mentioned that the spPosition, spRotation are ignored. I remember seeing that if you export matrices (bake transforms/matricies – something like that) that those matrices are used instead the nodal transform and rotation attributes.
Is that 30 draw call limit on the average or does it depend on your buffer sizes? I’m curious because my sprite system doesn’t bake everything out into a single draw call. There’s one draw call per quad, but I thought that’d be fine since it’s just a quad and I’m just going to be using it for a few UI things like progress bars and buttons.
I actually had a similar issue where the sdk didn’t provide functionality. I wanted to be able to swap out skeletons for a skinned mesh. There doesn’t seem to be a facility for this so I ended up stacking animation states/timelines back to back and creating a system to play sections of the timeline. I don’t really have the time to develop a new animation system, but things like that make me wonder if doing so would be better in the long run. It would be nice if they gave us the source for their exporters too so that I wouldn’t have to start from scratch. But oh well. It’s rude to complain about a free lunch I suppose.
Let me know what you end up doing for this. I’m curious if you’ll have to hack it or not.
-GregJuly 20, 2009 at 10:14 am #33137
gtmacdonald, bones and other deep trees of parenting is exactly the reason for the cache’s existence. I added it after realising just how much matrix transformation was required for the ChameleonMan demo – to calculate the matrix for a given node involved the three transforms I listed above, repeated for each anscestor. And if a node had N children, that whole chain is re-calculated N times. Hence we have the cache that will hold data for the current frame position, and the dedicated frame-0 cache, since all boned objects are back-transformed to that every time; without it the cache simply thrashes and gives little benefit.rbgames, none of our demos currently do what you describe, ie procedurally animating a node deep within the tree. However there is a function CPVRTModelPOD::FlushCache() that would force the NoCache version to be called each time you modify the data. You could modify your local copy to allow a range of nodes to be specified to FlushCache().Aaron.July 20, 2009 at 4:33 pm #33138
Thanks Aaron, I will look into that, for now, I am just adding a frame_num per Node, instead of Scene based, that way I can set each bone to a different frame of an animation.
RBGamesJuly 21, 2009 at 5:45 am #33139
Thanks Aaron for the clarification.
I’m still curious as to why you’re using frame zero. Was I correct in assuming that the mesh verts are baked out to the frame zero position? In other words, are you storing the bind pose in the pod file?
-GregJuly 21, 2009 at 8:58 am #33140gtmacdonald wrote:I’m still curious as to why you’re using frame zero.Because there’s always a frame zero…gtmacdonald wrote:Was I correct in assuming that the mesh verts are baked out to the frame zero position?Yes, although if you look at the 3ds max exporter dialog box there’s an option to select a different frame from the animation as the base pose, but I believe that should only affect exports with animation disabled. I’m not too sure how well exercised that code path is, I don’t recall ever having heard of anyone using it (and thus our other exporters don’t even have the option).Regards,Aaron.