<p>When transforming normal vectors we have to be careful to check that the transform itself is equal to its own inverse transpose. Or just do an inverse transpose on the matrix. This is usually the case, but checking it makes the requirement explicit rather then implied. (a scale in the transform for example would result in incorrect normal vectors)</p>
<p>When transforming a matrix from one coordinate system to another where we have a matrix M that transforms vectors from coordinate system A to coordinate system B then the transform from A to B is <span class="math-container">$B=MAM^{-1}$</span></p>

CC BY-SA 4.0
2022-11-12T14:56:18.133Z
2022-11-12T14:56:18.133Z
pmw1234
<p>I had the same question as you, and finally figured out a simple answer.</p>
<p>Add a new node to your glTF file.  Make this node the parent of both the mesh node and the skeleton (root bone node).  Then you can simply apply any transformations to this new root node, and they will affect the mesh, skeleton, and all animations, without having to do any matrix or vector math:</p>
<pre><code>&quot;scene&quot;: 0, 
  &quot;scenes&quot;: [
    {
      &quot;nodes&quot;: [0]
    }
  ],
  &quot;nodes&quot;: [
    {
      &quot;name&quot;: &quot;root node&quot;,
      &quot;children&quot;: [1, 2],
      *** Add your translation, rotation, and/or scale here ***
    },
    {
      &quot;mesh&quot;: 0,
      &quot;skin&quot;: 0
    },
    {
      &quot;name&quot;: &quot;bone0&quot;
      &quot;children&quot;: [3],
      &quot;translation&quot;: [0, 0, 0],
      &quot;rotation&quot;: [0, 0, 0, 1],
      &quot;scale&quot;: [1, 1, 1]
    }
    {
      &quot;name&quot;: &quot;bone1&quot;
      &quot;children&quot;: [...],
      &quot;translation&quot;: [0, 0, 0],
      &quot;rotation&quot;: [0, 0, 0, 1],
      &quot;scale&quot;: [1, 1, 1]
    },
    ...
  ], ...
</code></pre>

CC BY-SA 4.0
2024-06-15T23:18:23.537Z
This does not address the issue as this is not rotating the data. It is modifying the hierarchy so that a transformation is applied during rendering. Those are not the same thing.
Makogan
CC BY-SA 4.0
2024-06-11T19:16:38.967Z
2024-06-11T19:16:38.967Z
nanoguy
<p>I am trying to transform the mesh data in a gltf file and then modify the skin and animation data accordingly.</p>
<p>Let's say we want to transform the data using a 4x4 homogeneous matrix. For simplification let us say the transformation is just swapping the y and z axes.</p>
<p>Doing it to the mesh data is simple enough:</p>
<p>Something like this:</p>
<pre class="lang-rust prettyprint-override"><code>for mesh in &amp;gltf.meshes
    {
        for primitive in &amp;mesh.primitives
        {
            for position in gltf
                .data_from_accessor::&lt;Vec3&gt;(primitive.attributes.position)
                .unwrap()
            {
                *position = transform_vec3(&amp;position, &amp;transform, true);
            }

            for normal in gltf
                .data_from_accessor::&lt;Vec3&gt;(primitive.attributes.normal)
                .unwrap()
            {
                *normal = transform_vec3(&amp;normal, &amp;transform, false);
            }
        }
    }
</code></pre>
<p>Now the issue is, after doing this, what must we do to the skin data and animation data to correctly change it so that now the y and z axes are swapped.</p>
<p>We know that before our transformation, the animations are effectively computed as:</p>
<p><span class="math-container">$$(\sum \lambda_i A_i \cdot M_i) \cdot v$$</span></p>
<p>where <span class="math-container">$\lambda_i, A_i, M_i$</span> are the weights, animation matrices and inverse bind matrices.</p>
<p>Now, after modifying the vertices of the mesh data we have:</p>
<p><span class="math-container">$$(\sum \lambda_i A_i \cdot M_i) \cdot T v$$</span></p>
<p>So we need to modify our matrices such that the transformation <span class="math-container">$T$</span> is applied only once after all other transformations are applied, so:</p>
<p><span class="math-container">$$T(\sum \lambda_i A_i \cdot M_i)T^{-1} T v$$</span>
<span class="math-container">$$(\sum \lambda_i TA_i \cdot M_iT^{-1}) T v$$</span></p>
<p>The above formula suggests that the correct approach is to apply the transformation to all animation data and its inverse to the ibms.</p>
<p>Something like:</p>
<ul>
<li>for each ibm matrix ibm -&gt; ibm * <span class="math-container">$T^{-1}$</span></li>
<li>for each node in the skin node -&gt; <span class="math-container">$T$</span> * node</li>
<li>for each animation output in the skin, output -&gt; <span class="math-container">$T$</span> * output</li>
</ul>
<p>This fails miserably in all real life data I try and I don't understand why. For example this is the result on a model:</p>
<p><a href="https://i.sstatic.net/mZZTa.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/mZZTa.png" alt="enter image description here" /></a></p>
<p>If I remove the skins from the model I get this:</p>
<p><a href="https://i.sstatic.net/80Vaa.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/80Vaa.png" alt="enter image description here" /></a></p>
<p>Which is the expected output, the mesh data has flipped the z and the y.</p>
<p>So what must be done to convert the animation data to match the transform to the mesh?</p>

CC BY-SA 4.0
2022-11-12T20:04:01.300Z
Node transforms are hierarchical, so would it work to just apply the transform to the root node(s) of the file (or create a new root node to hold your transform, and make it the parent of all the file's root nodes)? Or are you trying to actually remove all transforms by baking them onto all the bottom-level vertex and animation data?
Nathan Reed
CC BY-SA 4.0
2022-11-13T06:29:29.840Z
@NathanReed I am trying to mutate 100% of all the data. So in the original data, y is up. I am trying to change it so that z is up. 

Maybe I am wrong but that sounds like every single datum that uses coordinates must have it's data altered.

Transform is a matrix because I want to later use this same logic to also translate/rotate the model data to change the origin.
Makogan
CC BY-SA 4.0
2022-11-14T15:03:22.407Z
OK, that definitely sounds like something where you just want to alter the root transform and let it automatically affect everything under it through the transform hierarchy.
Nathan Reed
CC BY-SA 4.0
2022-11-15T08:44:42.080Z
@NathanReed It will be wrong, I need to modify the mesh as well, so the mesh will have been modified such that all its x,y coords are flipped, so the nodes are wrong unless tehya re modified to.
Makogan
CC BY-SA 4.0
2022-11-15T14:56:27.227Z
What I'm saying is you can flip the coordinates with a matrix on the top level node. You don't need to modify the individual mesh vertices at all. It's just a rotation.
Nathan Reed
CC BY-SA 4.0
2022-11-30T07:19:09.170Z
@NathanReed But I do need to modify the mesh vertices, that's part of the goal, because I need to do some shape analysis on the mesh without the animation data.
Makogan
<transformations><animation><model><gltf>
How to apply a linear transformation to gltf data
Makogan
# How to apply a linear transformation to gltf data

(Asked by: username_0 on 2022-11-12)

I am trying to transform the mesh data in a gltf file and then modify the skin and animation data accordingly.

Let's say we want to transform the data using a 4x4 homogeneous matrix. For simplification let us say the transformation is just swapping the y and z axes.

Doing it to the mesh data is simple enough:

Something like this:

```rust
for mesh in &gltf.meshes
    {
        for primitive in &mesh.primitives
        {
            for position in gltf
                .data_from_accessor::<Vec3>(primitive.attributes.position)
                .unwrap()
            {
                *position = transform_vec3(&position, &transform, true);
            }

            for normal in gltf
                .data_from_accessor::<Vec3>(primitive.attributes.normal)
                .unwrap()
            {
                *normal = transform_vec3(&normal, &transform, false);
            }
        }
    }

```

Now the issue is, after doing this, what must we do to the skin data and animation data to correctly change it so that now the y and z axes are swapped.

We know that before our transformation, the animations are effectively computed as:

$$(\sum \lambda\_i A\_i \cdot M\_i) \cdot v$$

where $\lambda\_i, A\_i, M\_i$ are the weights, animation matrices and inverse bind matrices.

Now, after modifying the vertices of the mesh data we have:

$$(\sum \lambda\_i A\_i \cdot M\_i) \cdot T v$$

So we need to modify our matrices such that the transformation $T$ is applied only once after all other transformations are applied, so:

$$T(\sum \lambda\_i A\_i \cdot M\_i)T^{-1} T v$$
$$(\sum \lambda\_i TA\_i \cdot M\_iT^{-1}) T v$$

The above formula suggests that the correct approach is to apply the transformation to all animation data and its inverse to the ibms.

Something like:

* for each ibm matrix ibm -> ibm \* $T^{-1}$
* for each node in the skin node -> $T$ \* node
* for each animation output in the skin, output -> $T$ \* output

This fails miserably in all real life data I try and I don't understand why. For example this is the result on a model:

[![enter image description here](https://i.sstatic.net/mZZTa.png)](https://i.sstatic.net/mZZTa.png)

If I remove the skins from the model I get this:

[![enter image description here](https://i.sstatic.net/80Vaa.png)](https://i.sstatic.net/80Vaa.png)

Which is the expected output, the mesh data has flipped the z and the y.

So what must be done to convert the animation data to match the transform to the mesh?

**Tags:** transformations, animation, model, gltf

> **Comments:**
> **username_1**: Node transforms are hierarchical, so would it work to just apply the transform to the root node(s) of the file (or create a new root node to hold your transform, and make it the parent of all the file's root nodes)? Or are you trying to actually remove all transforms by baking them onto all the bottom-level vertex and animation data?  
> **username_0**: @username_1 I am trying to mutate 100% of all the data. So in the original data, y is up. I am trying to change it so that z is up.   Maybe I am wrong but that sounds like every single datum that uses coordinates must have it's data altered.  Transform is a matrix because I want to later use this same logic to also translate/rotate the model data to change the origin.  
> **username_1**: OK, that definitely sounds like something where you just want to alter the root transform and let it automatically affect everything under it through the transform hierarchy.  
> **username_0**: @username_1 It will be wrong, I need to modify the mesh as well, so the mesh will have been modified such that all its x,y coords are flipped, so the nodes are wrong unless tehya re modified to.  
> **username_1**: What I'm saying is you can flip the coordinates with a matrix on the top level node. You don't need to modify the individual mesh vertices at all. It's just a rotation.  
> **username_0**: @username_1 But I do need to modify the mesh vertices, that's part of the goal, because I need to do some shape analysis on the mesh without the animation data.  

---

## 2 answers

### Answer by username_2 on 2022-11-12. Score: 1

When transforming normal vectors we have to be careful to check that the transform itself is equal to its own inverse transpose. Or just do an inverse transpose on the matrix. This is usually the case, but checking it makes the requirement explicit rather then implied. (a scale in the transform for example would result in incorrect normal vectors)

When transforming a matrix from one coordinate system to another where we have a matrix M that transforms vectors from coordinate system A to coordinate system B then the transform from A to B is $B=MAM^{-1}$


---

### Answer by username_3 on 2024-06-11. Score: 0

I had the same question as you, and finally figured out a simple answer.

Add a new node to your glTF file. Make this node the parent of both the mesh node and the skeleton (root bone node). Then you can simply apply any transformations to this new root node, and they will affect the mesh, skeleton, and all animations, without having to do any matrix or vector math:

```
"scene": 0, 
  "scenes": [
    {
      "nodes": [0]
    }
  ],
  "nodes": [
    {
      "name": "root node",
      "children": [1, 2],
      *** Add your translation, rotation, and/or scale here ***
    },
    {
      "mesh": 0,
      "skin": 0
    },
    {
      "name": "bone0"
      "children": [3],
      "translation": [0, 0, 0],
      "rotation": [0, 0, 0, 1],
      "scale": [1, 1, 1]
    }
    {
      "name": "bone1"
      "children": [...],
      "translation": [0, 0, 0],
      "rotation": [0, 0, 0, 1],
      "scale": [1, 1, 1]
    },
    ...
  ], ...

```

> **Comments:**
> **username_0**: This does not address the issue as this is not rotating the data. It is modifying the hierarchy so that a transformation is applied during rendering. Those are not the same thing.  

---

