Hi.
I'm trying to change the way Irrlicht deal with bone animations. Questions are 100% related to C++
If this work, then we could have each animated scene node, have it's own data for each instance of a model. Used with "useAnimationFrom" (will need a version of this command in the AnimatedSceneNode to make this work too). So users could set animations on multiple instances of the same model quite easily. I just not sure on C++ way of doing this.
Since this should only affect the bone animations, it should not interfere with Hardware skinning when it's implemented. (hopefully)
Right now:
- Loader load the animation data in the mesh (Skinnedmesh class)
- Bone animation is stored and used to playback in the mesh (Skinnedmesh class), it's currently stored in an array named AllJoints (based on the SJoint struct)
- Each instance of the mesh refer to the same data, data is referenced not copied from node to node.
- The information is stored in a struct named SJoint inside the Skinnedmesh class
The SJoint struct is defined in the include header file: ISkinnedMesh.h
What I would like to do:
- Loader load the animation data in the mesh (Skinned mesh) (no change)
- Bone animation is referenced, and playback outside the mesh (AnimatedSceneNode class)
- When the node is instanced, it copies the data from the Skinned mesh to the AnimatedSceneNode container preferably called the same (AllJoints)
- The information is stored in a struct named SJoint inside the AnimatedSceneNode class
Questions:
1. Do I have to create the same struct inside the other class (AnimatedSceneNode)? Or there is a easier method?
2. Do I have to create getter and setter to transfert(copy) the data(array) from the SkinnedMesh class to the AnimatedSceneNode class?
3. How can I tell the SkinnedMesh class to refer to the data in the AnimatedSceneNode Class. AnimatedSceneNode sending a reference to it's own data to use? The playback of the bone animation is done in the SkinnedMesh class. The playback need to refer to AllJoints in the Animated scene node class and not use the one in the skinnedmesh class.
C++ questions on sharing structs from classes.
-
- Posts: 1638
- Joined: Mon Apr 30, 2007 3:24 am
- Location: Montreal, CANADA
- Contact:
Re: C++ questions on sharing structs from classes.
You are getting way ahead of yourself here. I suggest you try to write a bit of code just to see how it all fits together. For example, the actual mesh is stored in the joints (well, in the weights attached to the joints). In principle, I guess, it could be stored outside the node, though it contains the actual mesh. What is copied to the node is the current pose. For the purpose of storing the mesh, it could just be kept in one node, the "master". Other instances could have the joints stripped, though you do need to keep an independent view of where the animation is up to, so joint-like structures are needed.
Why not try to do something actual, like load two copies of a mesh and animate them independently. The you could get some idea of what is involved. Also note that Vetrotek has done some work with skinned meshes, but he has jettisoned the textures so it is not a good model to follow, but it may help you see how things fit together.
Why not try to do something actual, like load two copies of a mesh and animate them independently. The you could get some idea of what is involved. Also note that Vetrotek has done some work with skinned meshes, but he has jettisoned the textures so it is not a good model to follow, but it may help you see how things fit together.
-
- Posts: 1638
- Joined: Mon Apr 30, 2007 3:24 am
- Location: Montreal, CANADA
- Contact:
Re: C++ questions on sharing structs from classes.
Thanks Mongoose7!
I think it would be better to only copy data related to the animation. There other stuff (good for the mesh), but not required to define the animations. I'll mimic only some part of the struct that are needed. So I will have to create a new struct in the animatedMeshSceneNode and use it to store the animation data.
What I need to do also is check how the mesh is animated in the animatedMeshSceneNode and send the right data and store as less as possible in the mesh. If instances of the skinned mesh need to be independent, less is better.
If I can do it, Irrlicht will only store the animation data and reference the same mesh. Will be more efficient and take less ram.
EDIT: Ok. Found one interesting thing... There is one bit of code in the AnimatedMeshScene node that accesses the skeleton data and display the skeleton. It's the same data structure that I need to access.
So here I should have all the reference code to access this struct data. At first I was thinking that I could simply copy the array (it contain only pointers), but If I want to later have a way to modify the animation data it could create problems (since the pointers are still in the mesh data). I will need to create a new array with ONLY what is required for the animation (in the node), and update the animation from this data.
Edit1:
I think I see from the code how the animation is treated, and use lots of interpolation. So I presume the data is saved by "key" frames, and depending on the "time" there is an interpolation from one frame to the next. I will have to see how the loader (I'll check the B3D Loader) populate the JOINT structure to be sure. I see that some transformations and hints(what are frames hints?) are stored and not quite sure why.
EDIT2: Ok I really feel like "Jon Snow" now! Lol!
Just found out that my knowledge of pointers (reference and deference) and memory allocation (heap vs stack) was missing some details after being a couple of days reading Irrlicht source code! I have to revisit documents about this on the net. I was mostly all allocating on the stack all the time without even thinking about it.
Edit 3: Getting something now. It's not yest working but I was able to do this:
- Have the Node class, take the JOINT information and store it
- Temporarily send back from the node to the skinnedmesh class in another JOINT information to be used for playback (node class to skinnedmesh)
- Have the skinned mesh use the other data as reference to play the animation instead of the old one.
This doesn't change anything now, but it's a proof that data can originate from the NODE, and that data can be stored in the node too. This just need to be improved so it work, like I would like it to be.
Found out what the hints were, it was the last frame that was played. The JOINT struct store reference information information and also "live" stuff (last frame played, current position, rotation, scale, etc) in the skinnedmesh class. This struct is quite complex and will take me time to figure out all the details. Looking at this, I think it's possible to store only the keyframe information in the node, but this will require more work. taking the whole JOINT array is easier but surely would eat a lot of ram, and store informations in the node that is not needed.
Now I need to find a way from the CSkinnedMesh class to get directly the info from the node. Or having the node change the POINTER of data each time I playback something.
Edit 4: Now I got the mecanic in place. Just need to make a new function "useAnimationFrom" into the AnimatedMeshSceneNode and test it with meshes. But right now, the node get the animation from the mesh, and the animation data is now played from the node instead of the mesh. The mesh still receive the transformations so we see it.
I think it would be better to only copy data related to the animation. There other stuff (good for the mesh), but not required to define the animations. I'll mimic only some part of the struct that are needed. So I will have to create a new struct in the animatedMeshSceneNode and use it to store the animation data.
What I need to do also is check how the mesh is animated in the animatedMeshSceneNode and send the right data and store as less as possible in the mesh. If instances of the skinned mesh need to be independent, less is better.
I was able to achieve that in IRB by renaming the mesh name in the Irrlicht cache, the new instance will load from disk and have 2 objects in memory, instead of referencing on a single one. Not the best but it worked without modifying Irrlicht.Why not try to do something actual, like load two copies of a mesh and animate them independently.
If I can do it, Irrlicht will only store the animation data and reference the same mesh. Will be more efficient and take less ram.
EDIT: Ok. Found one interesting thing... There is one bit of code in the AnimatedMeshScene node that accesses the skeleton data and display the skeleton. It's the same data structure that I need to access.
Code: Select all
if (DebugDataVisible & scene::EDS_SKELETON)
{
if (Mesh->getMeshType() == EAMT_SKINNED)
{
// draw skeleton
for (u32 g=0; g < ((ISkinnedMesh*)Mesh)->getAllJoints().size(); ++g)
{
ISkinnedMesh::SJoint *joint=((ISkinnedMesh*)Mesh)->getAllJoints()[g];
for (u32 n=0;n<joint->Children.size();++n)
{
driver->draw3DLine(joint->GlobalAnimatedMatrix.getTranslation(),
joint->Children[n]->GlobalAnimatedMatrix.getTranslation(),
video::SColor(255,51,66,255));
}
}
}
Edit1:
I think I see from the code how the animation is treated, and use lots of interpolation. So I presume the data is saved by "key" frames, and depending on the "time" there is an interpolation from one frame to the next. I will have to see how the loader (I'll check the B3D Loader) populate the JOINT structure to be sure. I see that some transformations and hints(what are frames hints?) are stored and not quite sure why.
EDIT2: Ok I really feel like "Jon Snow" now! Lol!
Just found out that my knowledge of pointers (reference and deference) and memory allocation (heap vs stack) was missing some details after being a couple of days reading Irrlicht source code! I have to revisit documents about this on the net. I was mostly all allocating on the stack all the time without even thinking about it.
Edit 3: Getting something now. It's not yest working but I was able to do this:
- Have the Node class, take the JOINT information and store it
- Temporarily send back from the node to the skinnedmesh class in another JOINT information to be used for playback (node class to skinnedmesh)
- Have the skinned mesh use the other data as reference to play the animation instead of the old one.
This doesn't change anything now, but it's a proof that data can originate from the NODE, and that data can be stored in the node too. This just need to be improved so it work, like I would like it to be.
Found out what the hints were, it was the last frame that was played. The JOINT struct store reference information information and also "live" stuff (last frame played, current position, rotation, scale, etc) in the skinnedmesh class. This struct is quite complex and will take me time to figure out all the details. Looking at this, I think it's possible to store only the keyframe information in the node, but this will require more work. taking the whole JOINT array is easier but surely would eat a lot of ram, and store informations in the node that is not needed.
Now I need to find a way from the CSkinnedMesh class to get directly the info from the node. Or having the node change the POINTER of data each time I playback something.
Edit 4: Now I got the mecanic in place. Just need to make a new function "useAnimationFrom" into the AnimatedMeshSceneNode and test it with meshes. But right now, the node get the animation from the mesh, and the animation data is now played from the node instead of the mesh. The mesh still receive the transformations so we see it.