Animation in gltf

I did the animation in mesh in which there was one door and I did the animation for all the door nodes, I started something like this.

export async function setupNodeAnimations(session: ISessionApi, viewport: any) {

const doorOutput = session.getOutputByName("Door").find((o) => !!o.material);
const doorNode = session.node.children.find((c) => c.name === doorOutput!.id)!;
const doorNodes = doorNode.children;
const doorNodeMap = new Map(doorNodes.map((node) => [node.id, node]));
    doorNodes.forEach((childNode) => {
        childNode.data.push(new InteractionData({ select: true }));
        childNode.updateVersion();
    });
    for (let i = 0; i < minLength; i++) {
        const doorChildNode = doorNodes[I];
      const animationDatum = animationData[i];
        const { direction, type, start, end, amplitude } = animationDatum;

        if (type === 'rotation') {
            const { pivot } = animationDatum;
            const { x, y, z } = pivot;
            const pivot_animation = vec3.fromValues(x, y, z);
            const angle = direction === 'L' ? -Math.PI / 2 : Math.PI / 2;
            const quat0 = quat.create();
            // console.log('Initial quaternion for door(start):', quat0);
            
            const quat1 = quat.setAxisAngle(quat.create(), vec3.fromValues(0, 0, 1), angle);
            // console.log('Final quaternion for door (end):', quat1);
            const times = [0, 1, 2, 3];
            const values = [
                quat0[0], quat0[1], quat0[2], quat0[3],
                quat1[0], quat1[1], quat1[2], quat1[3],
                quat1[0], quat1[1], quat1[2], quat1[3],
                quat0[0], quat0[1], quat0[2], quat0[3],
            ];

            const tracks: IAnimationTrack[] = [
                {
                    times: times,
                    node: doorChildNode,
                    values: values,
                    path: "rotation",
                    interpolation: "linear",
                    pivot: pivot_animation
                }
            ];

I did same for the translation animation.

But now the model has shifted to the gltf format and now it has BigDrawer, SmallDrawer, RightShutter, LeftShutter, previously we were checking ig the door has material and then looping for the child nodes of it. In this format the structure/ geometry is different for each type of drawer and shutter. So what will be the logic or the method of mapping the animation data to these doors and drawers separately and then animate them, what will be the syntax or the code for the gltf format.

@MajorMeerkatThe3rd Can you help me out in this?

Hello @Ankita_Kushwaha,

it depends a bit on how the model is structure, please have a discussion with the Grasshopper developer about that. In general, the workflow is very similar though:

  • If the objects BigDrawer, SmallDrawer, RightShutter, LeftShutter are separate outputs, you can get the node for each of these outputs by first getting the output API (with getOutputByName) and then working with the node property of that output.
  • If the objects BigDrawer, SmallDrawer, RightShutter, LeftShutter are names that are used within one output, you can get the nodes by calling getNodesByName on the output node.

Regarding the different structure within the geometry, this is also something that you can discuss with the Grasshopper developer. It’s possible to assign names to parts of the geometry, that would make it easier for you to know to which level in the node hierarchy to apply the animation.

Cheers, Michael

@MajorMeerkatThe3rd Can you help me in this? I’m very eager to learn this gltf animation process and logic.

Michael is currently out of office, he will review your request on his return.

Thank you so much for letting me know.

Hello @Ankita_Kushwaha,

sorry for the delay on the response, as I was on vacation.

I just had a look at your model, and you GH colleague already created a nice setup for you. Here is an example of how you can get the nodes for the BigDrawer, but it will be the same for all the other elements (if your GH colleague used the same setup, which I assume).

// find the geometry output with the correct name
const outputApi = sessionApi.getOutputByName("BigDrawer").find(o => o.format !== 'material');

// create a callback that reads out the correct node
// this is also where the animation is applied (I didn't do that here, but added a comment)
const callback = (newNode?: ITreeNode) => {
  if(!newNode) return;

  // find the node that is called "BigDrawer"
  // this is the naming that was used in GrassHopper
  const namedNode = newNode.getNodesByName("BigDrawer")[0];

  // TODO: use the children of this node to apply the animations to them
};

// assign the callback so that it gets exectued automatically, every time the output changes
outputApi.updateCallback = callback;
// call it once in the beginning manually
callback(outputApi.node);

Cheers, Michael

Hello @Ankita_Kushwaha,

first of all some clarifications:

  • The convertedObjects are the three.js objects that are created from the nodes in the scene tree. There shouldn’t be any reason to interact with them in this case.
  • The animations array will be empty as long as no AnimationData has been added to the scene.
  • Regarding the pivot points for the rotation, from the code you sent me I couldn’t see an issue, but I think in this case, this is just a matter of debugging. Are the correct pivots set in the correct animation data? Are the correct animation data connected to the correct nodes?

If you find any issue here that you consider a bug, please create a minimal example with CodeSandBox so that I can debug it.

Cheers, Michael