What's wrong with skinned meshes?

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
full.metal.coder
Posts: 68
Joined: Sat May 10, 2008 11:30 am
Contact:

What's wrong with skinned meshes?

Post by full.metal.coder »

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
piiichan
Posts: 59
Joined: Thu May 01, 2008 1:20 am
Location: New Caledonia (France - Pacific)
Contact:

Post by piiichan »

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?
The center of an object is set during the modeling process.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

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.
Image Image Image
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

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..
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.

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
full.metal.coder
Posts: 68
Joined: Sat May 10, 2008 11:30 am
Contact:

Post by full.metal.coder »

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 :

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;

	}
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...)
full.metal.coder
Posts: 68
Joined: Sat May 10, 2008 11:30 am
Contact:

Post by full.metal.coder »

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.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

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!
full.metal.coder
Posts: 68
Joined: Sat May 10, 2008 11:30 am
Contact:

Post by full.metal.coder »

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.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by 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.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
full.metal.coder
Posts: 68
Joined: Sat May 10, 2008 11:30 am
Contact:

Post by full.metal.coder »

well until now it does return a correct mesh... If however we bring per-node mesh buffers for skinned meshes then it will become irrelevant (though still correct strictly speaking...)
Luke
Admin
Posts: 449
Joined: Fri Jul 14, 2006 7:55 am
Location: Australia
Contact:

Post by Luke »

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.
rogerborg:
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.
Post Reply