<p>You're right, standard skinning pipelines don't produce correct normals. You get similar problems when using translation on joints, which is very common in facial animation. The only way to get a correct result is to take the average of the surrounding face normals - this is not information you will be able to get in the vertex shader, so you'll have to use a geometry shader or run your skinning on CPU or a compute shader. </p>

CC BY-SA 3.0
2017-02-07T03:24:59.937Z
For sake of OpenGL 2.X, I'll probably stick with CPU skinning. Good to hear I'm not misunderstanding things.
lowq
CC BY-SA 3.0
2017-02-06T16:41:25.357Z
2017-02-06T16:41:25.357Z
James Answer
<p>I'm implementing mesh skinning in a project of mine. I can calculate vertex positions based on bone transformations, but I've run into a problem with calculating their normals.</p>

<p>From the resources I've read, it appears that a given vertex's skinned normal is the weighted sum of each influencing bone's transform applied to the vertex's normal.</p>

<p>What I don't understand, is how this would produce equivalent normals to what you <em>would</em> get if you calculated each vertex's normal directly. (I.E. from the sum of the normals of its adjacent faces)</p>

<p>For example, consider the case of three connected vertices with the normals shown below. Note the bone in the center, which has the same position as the center vertex.</p>

<p><a href="https://i.sstatic.net/stboN.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/stboN.png" alt="A simple rigged mesh"></a></p>

<p>Next, suppose this bone is turned 45 degrees CCW. If this bone only influenced the vertex to its right, my understanding is that it would produce the following result:</p>

<p><a href="https://i.sstatic.net/mQfeC.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/mQfeC.png" alt="Single influenced vertex"></a></p>

<p>This is because there is only one influencing bone, and the normal is rotated by the same rotation as the bone, 45 degrees CCW.</p>

<p>Next, consider that the bone influenced the middle <em>and</em> right vertices. Each vertex's normal would be rotated exactly as in the previous image.</p>

<p><a href="https://i.sstatic.net/MG97U.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/MG97U.png" alt="Two influenced vertices"></a></p>

<p>But, neither of these would produce the "correct" normal for the middle vertex, shown here:</p>

<p><a href="https://i.sstatic.net/dKPYh.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/dKPYh.png" alt="Presumably the correct middle normal"></a></p>

<p>So, my question is, is this the intended behavior for this algorithm? Is it only meant to be an approximation, or have I missed something critical? How are these normals meant to be calculated?</p>

<p>For what it's worth, the resources I've been following are presented <a href="http://web.archive.org/web/20161027175806/http://ruh.li/AnimationVertexSkinning.html" rel="nofollow noreferrer">here</a> and <a href="http://www.3dgep.com/loading-and-animating-md5-models-with-opengl/#The_MD5Model::PrepareMesh_Method" rel="nofollow noreferrer">here</a>.</p>

CC BY-SA 3.0
2017-02-03T08:35:46.477Z
what if the vertex used both matrices (blended) to calculate the normal
ratchet freak
CC BY-SA 4.0
2021-04-11T02:38:50.917Z
Yes it's an approximation, see "Accurate and Efficient Lighting for Skinned Models" http://vcg.isti.cnr.it/deformFactors/ if you'd like to implement a more accurate version (they provide code)
arkan
<algorithm><mesh><animation>
Calculating Skeleton-Deformed Mesh Normals
lowq
# Calculating Skeleton-Deformed Mesh Normals

(Asked by: username_0 on 2017-02-03)

I'm implementing mesh skinning in a project of mine. I can calculate vertex positions based on bone transformations, but I've run into a problem with calculating their normals.

From the resources I've read, it appears that a given vertex's skinned normal is the weighted sum of each influencing bone's transform applied to the vertex's normal.

What I don't understand, is how this would produce equivalent normals to what you *would* get if you calculated each vertex's normal directly. (I.E. from the sum of the normals of its adjacent faces)

For example, consider the case of three connected vertices with the normals shown below. Note the bone in the center, which has the same position as the center vertex.

[![A simple rigged mesh](https://i.sstatic.net/stboN.png)](https://i.sstatic.net/stboN.png)

Next, suppose this bone is turned 45 degrees CCW. If this bone only influenced the vertex to its right, my understanding is that it would produce the following result:

[![Single influenced vertex](https://i.sstatic.net/mQfeC.png)](https://i.sstatic.net/mQfeC.png)

This is because there is only one influencing bone, and the normal is rotated by the same rotation as the bone, 45 degrees CCW.

Next, consider that the bone influenced the middle *and* right vertices. Each vertex's normal would be rotated exactly as in the previous image.

[![Two influenced vertices](https://i.sstatic.net/MG97U.png)](https://i.sstatic.net/MG97U.png)

But, neither of these would produce the "correct" normal for the middle vertex, shown here:

[![Presumably the correct middle normal](https://i.sstatic.net/dKPYh.png)](https://i.sstatic.net/dKPYh.png)

So, my question is, is this the intended behavior for this algorithm? Is it only meant to be an approximation, or have I missed something critical? How are these normals meant to be calculated?

For what it's worth, the resources I've been following are presented [here](http://web.archive.org/web/20161027175806/http://ruh.li/AnimationVertexSkinning.html) and [here](http://www.3dgep.com/loading-and-animating-md5-models-with-opengl/#The_MD5Model::PrepareMesh_Method).

**Tags:** algorithm, mesh, animation

> **Comments:**
> **username_1**: what if the vertex used both matrices (blended) to calculate the normal  
> **username_2**: Yes it's an approximation, see "Accurate and Efficient Lighting for Skinned Models" http://vcg.isti.cnr.it/deformFactors/ if you'd like to implement a more accurate version (they provide code)  

---

## 1 answers

### Answer by username_3 on 2017-02-06. Score: 3 | Accepted answer

You're right, standard skinning pipelines don't produce correct normals. You get similar problems when using translation on joints, which is very common in facial animation. The only way to get a correct result is to take the average of the surrounding face normals - this is not information you will be able to get in the vertex shader, so you'll have to use a geometry shader or run your skinning on CPU or a compute shader.

> **Comments:**
> **username_0**: For sake of OpenGL 2.X, I'll probably stick with CPU skinning. Good to hear I'm not misunderstanding things.  

---

