useAnimationFrom problem
useAnimationFrom problem
Hi!
Thinking I was smart I tried to mix animations and skinned meshes together using useAnimationFrom().
Basically I load up Meshes containing characters (ie. Human, Skeleton, Orc...) at startup,
then I load up animations (ie. Idle, Run, Attack...), also at startup.
Both are B3D files and scene::ISkinnedMesh:es (Meshes contains a Mesh + Bones, Animations contains Bones+Animation).
At runtime when I want to draw a running orc I add a node created with :
node[m_PlayerID]=smgr->addAnimatedMeshSceneNode(NewMesh,RootNode,m_PlayerID);
(m_PlayerID here is an exclusive ID for this "Orc-Player")
where NewMesh points on the preloaded Orc ISkinnedMesh.
I then use
scene::ISkinnedMesh* SkinMesh=(scene::ISkinnedMesh*)node[m_PlayerID]->getMesh();
SkinMesh->useAnimationFrom(NewAnimationMesh);
node[m_PlayerID]->setFrameLoop(0, 60);
where NewAnimationMesh is the preloaded ISkinnedMesh containing the run animation.
This all works well except when I want to draw another Orc (Attacking) at the same time...
(A running Orc + an attacking Human works Okay).
They're getting the same animation!
(ie. both are attacking).
I use:
node[m_PlayerID]->setCurrentFrame(frame);
node[m_PlayerID]->animateJoints(true);
for each node too, but they're ending up with the same frame too.
What I got is that I'm doing all bone-manipulation on like 'one set of bones' and all meshes (of one type) uses it, but how can I get around that?
Do I need to clone the animation mesh each time I want to use one (or the Orc mesh?) of them or have I missed something here?
Thinking I was smart I tried to mix animations and skinned meshes together using useAnimationFrom().
Basically I load up Meshes containing characters (ie. Human, Skeleton, Orc...) at startup,
then I load up animations (ie. Idle, Run, Attack...), also at startup.
Both are B3D files and scene::ISkinnedMesh:es (Meshes contains a Mesh + Bones, Animations contains Bones+Animation).
At runtime when I want to draw a running orc I add a node created with :
node[m_PlayerID]=smgr->addAnimatedMeshSceneNode(NewMesh,RootNode,m_PlayerID);
(m_PlayerID here is an exclusive ID for this "Orc-Player")
where NewMesh points on the preloaded Orc ISkinnedMesh.
I then use
scene::ISkinnedMesh* SkinMesh=(scene::ISkinnedMesh*)node[m_PlayerID]->getMesh();
SkinMesh->useAnimationFrom(NewAnimationMesh);
node[m_PlayerID]->setFrameLoop(0, 60);
where NewAnimationMesh is the preloaded ISkinnedMesh containing the run animation.
This all works well except when I want to draw another Orc (Attacking) at the same time...
(A running Orc + an attacking Human works Okay).
They're getting the same animation!
(ie. both are attacking).
I use:
node[m_PlayerID]->setCurrentFrame(frame);
node[m_PlayerID]->animateJoints(true);
for each node too, but they're ending up with the same frame too.
What I got is that I'm doing all bone-manipulation on like 'one set of bones' and all meshes (of one type) uses it, but how can I get around that?
Do I need to clone the animation mesh each time I want to use one (or the Orc mesh?) of them or have I missed something here?
Re: useAnimationFrom problem
I think that SkinMesh pointer points at the same Iskinnedmesh you use for all Orcs (the NewMesh from the addAnimatedMeshSceneNode), changing that mesh animations changes the animations for all nodes using it as animations are stored in mesh, not in nodesValmond wrote:...
...
At runtime when I want to draw a running orc I add a node created with :
node[m_PlayerID]=smgr->addAnimatedMeshSceneNode(NewMesh,RootNode,m_PlayerID);
where NewMesh points on the preloaded Orc ISkinnedMesh.
I then use
scene::ISkinnedMesh* SkinMesh=(scene::ISkinnedMesh*)node[m_PlayerID]->getMesh();
SkinMesh->useAnimationFrom(NewAnimationMesh);
node[m_PlayerID]->setFrameLoop(0, 60);
...
...
Do I need to clone the animation mesh each time I want to use one (or the Orc mesh?) of them or have I missed something here?
I thought only 3 workarounds (2 of them are similar) for this:
1)(less flexible but probably requires less memory) put all the animations in a single skinnedmesh with different frames (0-60 run, 61-120 attack and so on) instead of one skinnedmesh for every animation
2)(faster and easier to implement but don't use this if you need many nodes in this way or it will fill all your memory) for every node clone the NewMesh into a new skinnedMesh (remember to delete it when you delete the node)
3)for every animation of your Orcs create a skinned mesh and apply the animation, then change the mesh of your node with the one you need, you could also do this on runtime (create the runningorc skinned mesh the first time you need to make an orc run, then use it for every orc that need to run)
I don't know but there is probably a simple way to chain 2 or more meshes togheter (if there is you can combine it with the third method to create a single mesh containing all of your orc animations and use it for all the orcs like method 1 but keeping the flexibility to add new animations easily)
Sorry for my awful english ^_^'
I seem to have the same problem. Actually I missed that so far - it seems I accidentally tested all the time animations by selecting different meshes :-)
Well, anyway - right now there seems no way to actually copy a skinnedmesh or am I missing something? I guess I'm adding a copy function to the meshmanipulator tomorrow in my version, but maybe someone has a better solution?
Well, anyway - right now there seems no way to actually copy a skinnedmesh or am I missing something? I guess I'm adding a copy function to the meshmanipulator tomorrow in my version, but maybe someone has a better solution?
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Thanks Hayate, there are lot of fixes but all of them needs more memory / loading time etc. and for 1) that is exactly what I'm trying to code away
It seems like this code
node[m_PlayerID]->setCurrentFrame(frame);
node[m_PlayerID]->animateJoints(true);
is actually executed instantly and not on a per-node basis at render time and
it is executed on the original mesh (and not on cloned bones, which seems normal after all)...
Maybe a CustomSceneNode that does the setCurrentFrame() + animateJoints() at rendertime might do it?
@CuteAlien
If you find a solution them I'm interested
It seems like this code
node[m_PlayerID]->setCurrentFrame(frame);
node[m_PlayerID]->animateJoints(true);
is actually executed instantly and not on a per-node basis at render time and
it is executed on the original mesh (and not on cloned bones, which seems normal after all)...
Maybe a CustomSceneNode that does the setCurrentFrame() + animateJoints() at rendertime might do it?
@CuteAlien
If you find a solution them I'm interested
OK, can't promise my solution is perfect as I'm still struggling to understand how that stuff is done in Irrlicht, but at least it works.
It needs some patch to Irrlicht - (my Irrlicht version is around revision 1981 - which means shortly after Irrlicht 1.5 release). That adds a function to the meshmanipulator that creates a new ISkinnedMesh with the meshbuffers and joints of another ISkinnedMesh:
Now when I create Animation nodes I make sure skinned meshes are copied first:
That's basically it.
If you use Blender you might also be interested in my patch to gandalfs exporter: http://www.michaelzeilfelder.de/irrlicht.htm#Scripts
This patch allows to export meshes and animations separately, so I load just the mesh with bones into my scenenode. And then with useAnimationFrom I use meshes which only contain bones and animations.
It needs some patch to Irrlicht - (my Irrlicht version is around revision 1981 - which means shortly after Irrlicht 1.5 release). That adds a function to the meshmanipulator that creates a new ISkinnedMesh with the meshbuffers and joints of another ISkinnedMesh:
Code: Select all
diff -r 8ecc8dc21f86 lib/irrlicht/include/IMeshManipulator.h
--- a/lib/irrlicht/include/IMeshManipulator.h Fri Mar 06 17:24:47 2009 +0100
+++ b/lib/irrlicht/include/IMeshManipulator.h Wed Mar 11 03:04:11 2009 +0100
@@ -20,6 +20,7 @@
class IMesh;
class IMeshBuffer;
struct SMesh;
+ class ISkinnedMesh;
//! An interface for easy manipulation of meshes.
/** Scale, set alpha value, flip surfaces, and so on. This exists for
@@ -180,6 +181,13 @@
IReferenceCounted::drop() for more information. */
virtual IAnimatedMesh * createAnimatedMesh(IMesh* mesh,
scene::E_ANIMATED_MESH_TYPE type = scene::EAMT_UNKNOWN) const = 0;
+
+ //! Create a skinned mesh which has copied all meshbuffers and joints of the original mesh
+ /**
+ \param mesh Original mesh
+ \return Newly created skinned mesh. You should call drop() wehn you don't need it anymore.
+ See IReferenceCounted::drop() for more information. */
+ virtual ISkinnedMesh* createSkinnedMesh(ISkinnedMesh* mesh) const = 0;
};
} // end namespace scene
diff -r 8ecc8dc21f86 lib/irrlicht/source/Irrlicht/CMeshManipulator.cpp
--- a/lib/irrlicht/source/Irrlicht/CMeshManipulator.cpp Fri Mar 06 17:24:47 2009 +0100
+++ b/lib/irrlicht/source/Irrlicht/CMeshManipulator.cpp Wed Mar 11 03:04:11 2009 +0100
@@ -6,6 +6,7 @@
#include "SMesh.h"
#include "CMeshBuffer.h"
#include "SAnimatedMesh.h"
+#include "CSkinnedMesh.h"
#include "os.h"
namespace irr
@@ -1140,6 +1141,50 @@
return new SAnimatedMesh(mesh, type);
}
+//! Create a skinned mesh which has copied all meshbuffers and joints of the original mesh
+ISkinnedMesh* CMeshManipulator::createSkinnedMesh(ISkinnedMesh* mesh) const
+{
+ CSkinnedMesh * skinnedMesh = new CSkinnedMesh();
+
+ if ( !mesh )
+ return skinnedMesh;
+
+ for ( u32 i=0; i < mesh->getMeshBuffers().size(); ++i )
+ {
+ SSkinMeshBuffer * buffer = skinnedMesh->createBuffer();
+ *buffer = *(mesh->getMeshBuffers()[i]);
+ }
+
+ for ( u32 j=0; j < mesh->getAllJoints().size(); ++j )
+ {
+ CSkinnedMesh::SJoint *joint = skinnedMesh->createJoint();
+ *joint = *(mesh->getAllJoints()[j]);
+ }
+
+ // fix children pointers (they still have old pointers)
+ core::array<CSkinnedMesh::SJoint*> & newJoints = skinnedMesh->getAllJoints();
+ core::array<CSkinnedMesh::SJoint*> & oldJoints = mesh->getAllJoints();
+ for ( u32 i=0; i < newJoints.size(); ++i )
+ {
+ CSkinnedMesh::SJoint * joint = newJoints[i];
+ for ( u32 c=0; c < joint->Children.size(); ++c )
+ {
+ // the child is one of the oldJoints and must be replaced by the newjoint on the same index
+ for ( u32 k=0; k < oldJoints.size(); ++k )
+ {
+ if ( joint->Children[c] == oldJoints[k] )
+ {
+ joint->Children[c] = newJoints[k];
+ break;
+ }
+ }
+ }
+ }
+
+ skinnedMesh->finalize();
+
+ return skinnedMesh;
+}
} // end namespace scene
} // end namespace irr
diff -r 8ecc8dc21f86 lib/irrlicht/source/Irrlicht/CMeshManipulator.h
--- a/lib/irrlicht/source/Irrlicht/CMeshManipulator.h Fri Mar 06 17:24:47 2009 +0100
+++ b/lib/irrlicht/source/Irrlicht/CMeshManipulator.h Wed Mar 11 03:04:11 2009 +0100
@@ -106,6 +106,9 @@
//! create a new AnimatedMesh and adds the mesh to it
virtual IAnimatedMesh * createAnimatedMesh(scene::IMesh* mesh,scene::E_ANIMATED_MESH_TYPE type) const;
+ //! Create a skinned mesh which has copied all meshbuffersand joints of the original mesh
+ virtual ISkinnedMesh* createSkinnedMesh(ISkinnedMesh* mesh) const;
+
private:
static void calculateTangents(core::vector3df& normal,
Code: Select all
irr::scene::IAnimatedMesh * mesh = .... // whereever you get it from - probably from loading.
irr::scene::IAnimatedMeshSceneNode * node = 0;
if ( mesh->getMeshType() == scene::EAMT_SKINNED )
{
scene::IMeshManipulator * meshManip = sceneManager.getMeshManipulator();
scene::ISkinnedMesh * meshCopy = meshManip->createSkinnedMesh( static_cast<scene::ISkinnedMesh*>(mesh));
node = sceneManager.addAnimatedMeshSceneNode(meshCopy);
meshCopy->drop();
}
else
{
node = sceneManager.addAnimatedMeshSceneNode(mesh);
}
If you use Blender you might also be interested in my patch to gandalfs exporter: http://www.michaelzeilfelder.de/irrlicht.htm#Scripts
This patch allows to export meshes and animations separately, so I load just the mesh with bones into my scenenode. And then with useAnimationFrom I use meshes which only contain bones and animations.
Last edited by CuteAlien on Wed Mar 11, 2009 2:47 pm, edited 1 time in total.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
edit: *redface*
Last edited by CuteAlien on Wed Mar 11, 2009 2:48 pm, edited 1 time in total.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Guess that was too obvious for me ;-) Fixed now.hybrid wrote:Then just take it out :D You can simply remove the text and leave the comment start there, which wouldn't require any other change to the patch file.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
I'm not 100% happy with it so far. A create-function with a parameter that only uses part of that parameter (just enough to make this work). I'm not sure if this is intuitive to use (without reading this thread first). Also I'm not deep enough in the animation system to know if this covers all such problem or if it just works for my (and your) models or if any further data of CSkinnedMesh should be copied here.
I think Bitplane would prefer having the animationscenenodes handling the mesh-copies, which would be the easier-to-use solution. I avoided that as it would have made for patch that is more fused with other code and that sort of patches makes it in my experience harder for me to update my patches to newer engine versions.
Then again maybe a working solution is better than no solution at all. Anyway, the Irrlicht team is aware of the thread, so if they ever come around to handling this they have at least some basis to start.
I think Bitplane would prefer having the animationscenenodes handling the mesh-copies, which would be the easier-to-use solution. I avoided that as it would have made for patch that is more fused with other code and that sort of patches makes it in my experience harder for me to update my patches to newer engine versions.
Then again maybe a working solution is better than no solution at all. Anyway, the Irrlicht team is aware of the thread, so if they ever come around to handling this they have at least some basis to start.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
hi
sorry for hijacking your topic, but dun wanna open a new xD
I just dont understand why it doesn't animate joints what can't be found in the boneMesh?
it just doesn't make any sense...
If there is no matching joint in the boneMesh, then it should use the original animation from the skinMesh.
and of course, if no animation in the skinMesh, then it won't animate.
For example, for a cloak, in your boneMesh there is just the bones for the human, and in the cloak, there should be the cloak animation.
Its just cant be customized enough in this way..
and yeah we can put all the joints in the same mesh, but then it would be a great chaos xD
so i suggest it should copy animations when same bone has found, and use the original bone animation when not found.
sorry for hijacking your topic, but dun wanna open a new xD
I just dont understand why it doesn't animate joints what can't be found in the boneMesh?
it just doesn't make any sense...
If there is no matching joint in the boneMesh, then it should use the original animation from the skinMesh.
and of course, if no animation in the skinMesh, then it won't animate.
For example, for a cloak, in your boneMesh there is just the bones for the human, and in the cloak, there should be the cloak animation.
Its just cant be customized enough in this way..
and yeah we can put all the joints in the same mesh, but then it would be a great chaos xD
so i suggest it should copy animations when same bone has found, and use the original bone animation when not found.
I suppose in your example you should rather give the cloak it's own animation which is independent of the human animation.
I would not like to see parts of an old animation messing with a new animation which I have set. I guess there are situation where you might want to have several animations operating the same time at the same bones - and the second one having priority over the first is in that case one of the things you could wish for, but I don't think that is supported right now. I guess you could try animating a mesh twice with both animations and somehow checking first which bones are used by both animatios and then removing those for the first animation. But I think at the moment you would have to change Irrlicht itself for that.
I would not like to see parts of an old animation messing with a new animation which I have set. I guess there are situation where you might want to have several animations operating the same time at the same bones - and the second one having priority over the first is in that case one of the things you could wish for, but I don't think that is supported right now. I guess you could try animating a mesh twice with both animations and somehow checking first which bones are used by both animatios and then removing those for the first animation. But I think at the moment you would have to change Irrlicht itself for that.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
nope, because it would only use the original animation when the same joint name couldnt be found.
so the human animation would be loaded from the boneMesh, and the cloak animation from my skinMesh.
and i dont want to have several animations the same time at the same bones..
i cant even imagine it, whats that? O_o
so the human animation would be loaded from the boneMesh, and the cloak animation from my skinMesh.
and i dont want to have several animations the same time at the same bones..
i cant even imagine it, whats that? O_o