C++ questions on sharing structs from classes.

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

C++ questions on sharing structs from classes.

Post by christianclavet »

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.
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: C++ questions on sharing structs from classes.

Post by mongoose7 »

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.
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Re: C++ questions on sharing structs from classes.

Post by christianclavet »

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.
Why not try to do something actual, like load two copies of a mesh and animate them independently.
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.

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));
                    }
                }
            }
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.
Post Reply