What's wrong with skinned meshes?
-
- Posts: 68
- Joined: Sat May 10, 2008 11:30 am
- Contact:
What's wrong with skinned meshes?
I've been working on getting Irrlicht and Bullet to work together for quite some time and I came to something rather satisfying.
Up until I changed my test model from sydney.md2 to a b3d asset. I later tried with a variety of other b3d, ms3d and x files but the results are the same.
I'm using Bullet debug drawing to inspect my app and it appears that, contrary to MD2 meshes, skinned meshes somehow manage to hide their animations from the physics engine. Let me explain this point a bit more precisely :
IAnimatedMesh has a getMesh method. I've looked at the sources and noticed that this value was constant (either "this" or a pointer to a member) so I figured I could have animated mesh data passed to Bullet, which worked quite well with MD2 models but fails with skinned meshes while the source code clearly indicates that it should not... Any hints?
Another issue I'm facing is that skinned meshes do not have an origin smartly placed at the center of mass but instead under their feets which breaks parts of my character controller design. My question here is : is this an Irrlicht bug or is this to blame on the modellers?
best regards
Up until I changed my test model from sydney.md2 to a b3d asset. I later tried with a variety of other b3d, ms3d and x files but the results are the same.
I'm using Bullet debug drawing to inspect my app and it appears that, contrary to MD2 meshes, skinned meshes somehow manage to hide their animations from the physics engine. Let me explain this point a bit more precisely :
IAnimatedMesh has a getMesh method. I've looked at the sources and noticed that this value was constant (either "this" or a pointer to a member) so I figured I could have animated mesh data passed to Bullet, which worked quite well with MD2 models but fails with skinned meshes while the source code clearly indicates that it should not... Any hints?
Another issue I'm facing is that skinned meshes do not have an origin smartly placed at the center of mass but instead under their feets which breaks parts of my character controller design. My question here is : is this an Irrlicht bug or is this to blame on the modellers?
best regards
-
- Posts: 59
- Joined: Thu May 01, 2008 1:20 am
- Location: New Caledonia (France - Pacific)
- Contact:
The center of an object is set during the modeling process.Another issue I'm facing is that skinned meshes do not have an origin smartly placed at the center of mass but instead under their feets which breaks parts of my character controller design. My question here is : is this an Irrlicht bug or is this to blame on the modellers?
I think rogerborg keeps saying that the SkinnedMesh support is currently rather borked... it may be just the getJoint functions or maybe it's getMesh.. i forget..
piiichan is right, you set the center of a model when it's being modelled. possibly all MD2s are setup so that the centre is always the centre, if you see what i mean, rather than the feet. Seeing as they have to work in Quake 2 it could be a specification for them or maybe the exporter forces it.
I've come across this problem in my IrrAI work, getting models with different centres to me properly aligned to my NPC controllers so feel free to have a look at my code in the examples to see how i've achieved it and see if you can get the same thing to work for you. CityCharacter.cpp in the Calmageddon example should show you how to do it, check how i'm setting up the npc_offset and npc_scale from the model's bounding box in the constructor.
piiichan is right, you set the center of a model when it's being modelled. possibly all MD2s are setup so that the centre is always the centre, if you see what i mean, rather than the feet. Seeing as they have to work in Quake 2 it could be a specification for them or maybe the exporter forces it.
I've come across this problem in my IrrAI work, getting models with different centres to me properly aligned to my NPC controllers so feel free to have a look at my code in the examples to see how i've achieved it and see if you can get the same thing to work for you. CityCharacter.cpp in the Calmageddon example should show you how to do it, check how i'm setting up the npc_offset and npc_scale from the model's bounding box in the constructor.
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Yes, he does say that, but he can't always be trusted. Last I recall, he said that getMesh(s32 frame) didn't work, but you should probably verify that yourself before taking it at face value.JP wrote:I think rogerborg keeps saying that the SkinnedMesh support is currently rather borked... it may be just the getJoint functions or maybe it's getMesh.. i forget..
I wish he'd stop being so lazy and fix it himself, to be honest.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
-
- Posts: 68
- Joined: Sat May 10, 2008 11:30 am
- Contact:
And it indeed seems that the getMesh() function is not working fine. At least not as one would expect it to...
Here is the code from CAnimatedMeshSceneNode.cpp :
How the heck am I (or anyone else btw) supposed to get it to work with a physics engine? A good old bunch of mesh buffers gently updated by the mesh was anything I needed but it doesn't look like I can get skinned meshes to work this way?
Really it would be nice if skinned and "normal" meshes behaved consistently. I'm not sure if it is doable but it would certainly be interesting if skinned meshes had an option to force (or prevent) them from maintaining proper mesh buffers to share with a physics engine (or whatever else one might want to do with that data...)
Here is the code from CAnimatedMeshSceneNode.cpp :
Code: Select all
if (Mesh->getMeshType() != EAMT_SKINNED)
m = Mesh->getMesh((s32)frame, 255, StartFrame, EndFrame);
else
{
CSkinnedMesh* skinnedMesh = reinterpret_cast<CSkinnedMesh*>(Mesh);
if (JointMode == EJUOR_CONTROL)//write to mesh
skinnedMesh->transferJointsToMesh(JointChildSceneNodes);
else
skinnedMesh->animateMesh(frame, 1.0f);
skinnedMesh->skinMesh();
if (JointMode == EJUOR_READ)//read from mesh
{
skinnedMesh->recoverJointsFromMesh(JointChildSceneNodes);
//---slow---
for (u32 n=0;n<JointChildSceneNodes.size();++n)
if (JointChildSceneNodes[n]->getParent()==this)
{
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
}
}
m=skinnedMesh;
}
Really it would be nice if skinned and "normal" meshes behaved consistently. I'm not sure if it is doable but it would certainly be interesting if skinned meshes had an option to force (or prevent) them from maintaining proper mesh buffers to share with a physics engine (or whatever else one might want to do with that data...)
-
- Posts: 68
- Joined: Sat May 10, 2008 11:30 am
- Contact:
OK I found my problem :
skinned mesh animations are applied... in the render() function! I'll spare you my rant about coherent code and go on a bit.
skinned mesh animation could be done like any other mesh (have a look at CSkinnedMesh::getMesh() code if you don't believe me...) so there is no relevant reason to handle it in a special way as long as no special joint mode is set and even then animation ought to be doen in OnAnimate(), not in render()...
I guess I gotta post a patch for this in the bug thread.
skinned mesh animations are applied... in the render() function! I'll spare you my rant about coherent code and go on a bit.
skinned mesh animation could be done like any other mesh (have a look at CSkinnedMesh::getMesh() code if you don't believe me...) so there is no relevant reason to handle it in a special way as long as no special joint mode is set and even then animation ought to be doen in OnAnimate(), not in render()...
I guess I gotta post a patch for this in the bug thread.
-
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
Well, most is already said in the other post, but no, this won't work without much additional space used. Yes, this might be necessary, but it's not the only way to do it. So we will hav to make it an option somehow. It would also fix the problems with getMesh(n) for collisions etc. But it's a huge storage problem!
-
- Posts: 68
- Joined: Sat May 10, 2008 11:30 am
- Contact:
making it optional (with a per-node storage for animated mesh buffer) would probably be the best option. there is a choice to make here between speed and memory usage and it would be BAD (tm) to enforce one upon every developer. There is no better choice, it depends on the context and must thus be left to the user.
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Huzzah!. If you're up for sorting it, then I'd respectfully suggest that until and unless accurate per-node meshes are available, that IAnimatedMesh::getMesh(s32 frame,...) both assert (_IRR_DEBUG_BREAK_IF(...)) and return 0 for skinned meshes, rather than return an incorrect mesh.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
-
- Posts: 68
- Joined: Sat May 10, 2008 11:30 am
- Contact:
rogerborg:Huzzah!. If you're up for sorting it, then I'd respectfully suggest that until and unless accurate per-node meshes are available, that IAnimatedMesh::getMesh(s32 frame,...) both assert (_IRR_DEBUG_BREAK_IF(...)) and return 0 for skinned meshes, rather than return an incorrect mesh.
Even with per-node mesh data, IAnimatedMesh::getMesh(s32 frame,...) is not going to return the correct mesh.
I could make Node->GetMesh() animate the mesh before returning it (might wait till animation is stored pre-node so not slow) but I cannot make Mesh->getMesh() animate to some unknown node.
full.metal.coder:
try using,
StaticMesh = Mesh->getMesh(Node->getFrameNr());
it should return the correct mesh for your physics.