Qt3D - Import gltf and play animation

Viewed 247

I'm currently struggling to play the animation of a gltf-file with Qt3D/QML.

Model I want to use:

https://sketchfab.com/3d-models/plane-cedc8a07370747f7b0d14400cdf2faf9

Code I have so far:

 Entity {
    id: root

    Transform {
        id: planeTransform
        scale: 0.1
    }
    components: [
        planeClip,
        planeTransform,
        planeScene
    ]

    SceneLoader{
        id:planeScene
        source: "qrc:/Modells/3DModelle/plane/scene.gltf"
    }

    AnimationClipLoader{
        id: planeClipLoader
        source: "qrc:/Modells/3DModelle/plane/scene.gltf"
    }
    ClipAnimator{
        id: planeClip
        clip: planeClipLoader
        channelMapper: ChannelMapper {
            mappings: [  ] // Dont know where to get this
        }

        loops: Animation.Infinite
        running: true
    }

}

I use the SceneLoader to check if the gltf can be even loaded (it works, I can see the plane). But I'm struggling to start the animation because I don't know where I get the ChannelMapper from.

When I open the file with 3DViewer on Windows, it plays the Animation correctly, so I suppose it should work without much insider knowledge of the file itself.

Anyone here familiar with playing gltf animations?

Thanks for the help!

1 Answers

To do this you need to traverse the tree of Entity(s) build by SceneLoader and find the appropriate component to initialize ClipAnimator with.

It's going to look something like this:

SceneLoader {
    id: planeScene
    source: "qrc:/Modells/3DModelle/plane/scene.gltf"

    onStatusChanged: {
        console.log("SceneLoader status=" + status);
        if (status != SceneLoader.Ready)
            return;

        // retrieve a list of all the Entity(s) in the scene
        var entityNames = planeScene.entityNames();
        console.log("SceneLoader: entityNames=" + entityNames);

        // traverse the Entity tree
        for (var i = 0; i < entityNames.length; ++i) {
            var entityName = entityNames[i];      
            var entityVar = planeScene.entity(entityName);
            console.log("SceneLoader: entity=" + entityName + " components.length=" + entityVar.components.length);

            // iterate on the components of this Entity
            for (var j = 0; j < entityVar.components.length; ++j) {
                var cmp = entityVar.components[j];
                if (!cmp)
                    continue;

                var cmp_class = cmp.toString();
                console.log("SceneLoader:  -> " + cmp_class);

                // compare the type of this component to whatever type 
                // you are looking for. On this silly example, its QPhongMaterial:
                if (cmp_class.indexOf("QPhongMaterial") >= 0) {
                    // initialize ClipAnimator with this data
                }                
            }
        }
    }
}

I'm sharing the generic procedure here as I don't have a way to test this right now and figure out the data type you need to initialize ClipAnimator correctly.

Related