<p>You are not too far off with your second averaging approach. The problem is, that the area is the wrong weighting factor for what you want to achieve. You want each of the 3 sides of the cube to contribute equally to the vertex normal, but you need to extract the information from the adjacent triangles. The area and the number of triangles are bad weighting factors since they vary with the number of triangles per side. But one thing stays always the same at each vertex: The angle between two edges at the side. So you just need to take the angle of each triangle connected to the vertex and use it as a weighting factor for its normalized face normal. The weighting factors will always sum up to 90°/<span class="math-container">$\frac{\pi}{2}$</span> per side of the cube. Look for example at the bottom left vertex at the front in the image you posted.</p>

<p>Your first approach fails because it yields:</p>

<p><span class="math-container">$$N_v = \frac{2*N_l + 2 \cdot N_f + 1 \cdot N_b}{5}$$</span></p>

<p>where <span class="math-container">$N_l$</span> is the left, <span class="math-container">$N_f$</span> the front and <span class="math-container">$N_b$</span> the bottom side normal. Assume them to be normalized. The factors result from the triangle count at the vertex and their sum.</p>

<p>Your second approach fails because it yields: </p>

<p><span class="math-container">$$N_v = \frac{N_l + 0.5 \cdot N_f + 0.5 \cdot N_b}{2}$$</span></p>

<p>Here the factors result from the fact, that only the left face has all its triangles connected to the vertex. The bottom face connects only 1 of 2 and front face only 2 of 4 equally sized triangles to the vertex.</p>

<p>If you take the angles, you get:</p>

<p><span class="math-container">$$N_v = \frac{2\cdot 45 \cdot N_l + 2 \cdot 45 \cdot N_f+ 90 \cdot N_b}{270}$$</span></p>

<p>Now each side contributes equally and independent of the number and size of triangles connected to the vertex.</p>

<p><strong>EDIT:</strong></p>

<p>I just realized, that the front face also contains only 2 triangles. The diagonal of the back face triangles irritated me. However, this will not affect the conclusion but the weigting factors change. For the fist approach you get:</p>

<p><span class="math-container">$$N_v = \frac{2*N_l + 1 \cdot N_f + 1 \cdot N_b}{4}$$</span></p>

<p>The second remains unchanged and for the angles you get:</p>

<p><span class="math-container">$$N_v = \frac{2\cdot 45 \cdot N_l + 90 \cdot N_f+ 90 \cdot N_b}{270}$$</span></p>

<p>which is still correct. What is interesting is that both your approaches give the same results for the shown cube, since a connection of the vertex to 2 triangles also means that the area weight is doubled. You can also see this if you compare both pictures.</p>

CC BY-SA 4.0
2020-04-09T18:12:10.210Z
Using the angle worked
Makogan
CC BY-SA 4.0
2020-04-09T13:29:40.850Z
2020-04-09T17:44:16.767Z
2020-04-09T17:44:16.767Z
wychmaster
<p>Assuming you want to calculate the <em>shared</em> vertex normal... if you know which faces use the vertex and they have unitised normals.</p>

<p><span class="math-container">\begin{equation*}\left \| \sum \left \| n_{t} \right \| \right \|\end{equation*}</span></p>

<p>Your first appraoch is close, but would only work if the face normals are unitised otherwise they will skew.</p>

<p><a href="https://computergraphics.stackexchange.com/questions/4031/programmatically-generating-vertex-normals">See this question for more information</a></p>

<p>Given your last image, it looks like you want normals per face (flat shading) in which case you shouldn't share your vertices between faces, instead you need three vertices for each triangle (i.e 36 for a cube using tgriangles, or 24 for a cube if using quads).</p>

<p>If you want to use no more than 8 vertices, you will effectively get smooth shading (possibly what your first two images show) and not flat shading (what it looks like you want with your 3rd image), or you need to have normals per face (and not per vertex).</p>

CC BY-SA 4.0
2020-04-09T15:49:03.983Z
That's just doing the area weighted average of the face normals, it's just going about it differently than I am
Makogan
CC BY-SA 4.0
2020-04-09T15:53:58.853Z
@Makogan the vertex normal has nothing to do with area. When you say *calculate normal*, what is it do you mean exacatly? Did you check out the qu I linked to.
lfgtm
CC BY-SA 4.0
2020-04-09T15:57:01.587Z
I read the question you linked, what Inigo Quilez is doing is, he's adding the cross product then nromalizing the vertex, the cross product gives you  the normal times the area of the triangle times 2.

Then when you nromalize it, that;s equivalent to dividing by the norm, and the norm is equal to the sum of the areas of all trinagles times 2.

i.e the formula in the linked question is the same as averaging the face normals based on the area of the adjacent triangles.
Makogan
CC BY-SA 4.0
2020-04-09T18:00:19.170Z
@Makogan I see what you are saying, apologies my bad, you are looking for *face weighted* vertex normal rather than the vertex normal. This is not the correct normalisation to do for the topology you have then (i.e a cube, which has hard edges) and so not going to give you the answer you are looking for. Agree with wychmaster, you should weight the normals based on adjacent angle difference, and **not** area. The type of normalisation you wish to do depends on what you want it for (lighting, topology analysis etc), and the topology you have. What do you want the normal for?
lfgtm
CC BY-SA 4.0
2020-04-09T18:11:59.117Z
I need the normal to do afine scaling
Makogan
CC BY-SA 4.0
2020-04-09T15:31:25.810Z
2020-04-09T15:44:17.380Z
2020-04-09T15:44:17.380Z
lfgtm
<p>Assume you have a list of vertices and their connectivity information. (I.e you can find all the adjacent edges and faces to each vertex).</p>

<p>What is a good approach to calculate a normal from this information?</p>

<p>Currently I first tried naive averaging, i.e:</p>

<p><span class="math-container">$\frac{\sum n_i}{N}$</span></p>

<p>Where <span class="math-container">$n_i$</span> are the face normals and <span class="math-container">$N$</span> is the total number of faces</p>

<p>And I also tried:</p>

<p><span class="math-container">$\frac{\sum n_i * a_i}{A}$</span></p>

<p>Where <span class="math-container">$a_i$</span> are the respective areas of each face and <span class="math-container">$A$</span> is the sum of the areas of all adjacent faces.</p>

<p>The first gave me this:</p>

<p><a href="https://i.sstatic.net/5n4Rc.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/5n4Rc.png" alt="enter image description here"></a></p>

<p>The second gave me this:</p>

<p><a href="https://i.sstatic.net/Mht2J.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/Mht2J.png" alt="enter image description here"></a></p>

<p>What I want is:</p>

<p><a href="https://i.sstatic.net/rVP44.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/rVP44.png" alt="enter image description here"></a></p>

<p>That last image I obtained by setting the normal to be the vector from the origin to the vertex position, but this is only true for highly regular meshes like cubes and spheres, it doesn't hold generally. The data I am using to make this is just the default blender cube.</p>

<p>Increasing precision to doubles doesn't seem to affect the result. This is the wiremesh:</p>

<p><a href="https://i.sstatic.net/Hrj1f.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/Hrj1f.png" alt="enter image description here"></a></p>

<p>Obviously the issue occurs because the number of faces adjacent to a vertex isn't balanced, which skews the normals into certain directions, but I don;t know how to compensate for that</p>

CC BY-SA 4.0
2020-04-09T05:38:28.343Z
Do you normalise the length of the normal vectors before adding them together ?
PaulHK
CC BY-SA 4.0
2020-04-09T05:50:44.397Z
Yes, the error comes from the number of normals not their magnitudes.
Makogan
CC BY-SA 4.0
2020-04-09T06:09:16.527Z
Are the lengths of the normals 1 though ? The first pic looks like what happens when you sum up cross-products with normalising them.
PaulHK
CC BY-SA 4.0
2020-04-09T09:04:53.853Z
ETA: Given this is a simple cube we should be able to look at the normals with our eyes and know what to expect. Can you list an example of 1 vertex being computed along with all the face normals that are summed up into it ?
PaulHK
<computational-geometry><mesh><geometry><normal-mapping>
Calculate normals from vertices
Makogan
# Calculate normals from vertices

(Asked by: username_0 on 2020-04-08)

Assume you have a list of vertices and their connectivity information. (I.e you can find all the adjacent edges and faces to each vertex).

What is a good approach to calculate a normal from this information?

Currently I first tried naive averaging, i.e:

$\frac{\sum n\_i}{N}$

Where $n\_i$ are the face normals and $N$ is the total number of faces

And I also tried:

$\frac{\sum n\_i \* a\_i}{A}$

Where $a\_i$ are the respective areas of each face and $A$ is the sum of the areas of all adjacent faces.

The first gave me this:

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

The second gave me this:

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

What I want is:

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

That last image I obtained by setting the normal to be the vector from the origin to the vertex position, but this is only true for highly regular meshes like cubes and spheres, it doesn't hold generally. The data I am using to make this is just the default blender cube.

Increasing precision to doubles doesn't seem to affect the result. This is the wiremesh:

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

Obviously the issue occurs because the number of faces adjacent to a vertex isn't balanced, which skews the normals into certain directions, but I don;t know how to compensate for that

**Tags:** computational-geometry, mesh, geometry, normal-mapping

> **Comments:**
> **username_1**: Do you normalise the length of the normal vectors before adding them together ?  
> **username_0**: Yes, the error comes from the number of normals not their magnitudes.  
> **username_1**: Are the lengths of the normals 1 though ? The first pic looks like what happens when you sum up cross-products with normalising them.  
> **username_1**: ETA: Given this is a simple cube we should be able to look at the normals with our eyes and know what to expect. Can you list an example of 1 vertex being computed along with all the face normals that are summed up into it ?  

---

## 2 answers

### Answer by username_2 on 2020-04-09. Score: 3 | Accepted answer

You are not too far off with your second averaging approach. The problem is, that the area is the wrong weighting factor for what you want to achieve. You want each of the 3 sides of the cube to contribute equally to the vertex normal, but you need to extract the information from the adjacent triangles. The area and the number of triangles are bad weighting factors since they vary with the number of triangles per side. But one thing stays always the same at each vertex: The angle between two edges at the side. So you just need to take the angle of each triangle connected to the vertex and use it as a weighting factor for its normalized face normal. The weighting factors will always sum up to 90°/$\frac{\pi}{2}$ per side of the cube. Look for example at the bottom left vertex at the front in the image you posted.

Your first approach fails because it yields:

$$N\_v = \frac{2\*N\_l + 2 \cdot N\_f + 1 \cdot N\_b}{5}$$

where $N\_l$ is the left, $N\_f$ the front and $N\_b$ the bottom side normal. Assume them to be normalized. The factors result from the triangle count at the vertex and their sum.

Your second approach fails because it yields:

$$N\_v = \frac{N\_l + 0.5 \cdot N\_f + 0.5 \cdot N\_b}{2}$$

Here the factors result from the fact, that only the left face has all its triangles connected to the vertex. The bottom face connects only 1 of 2 and front face only 2 of 4 equally sized triangles to the vertex.

If you take the angles, you get:

$$N\_v = \frac{2\cdot 45 \cdot N\_l + 2 \cdot 45 \cdot N\_f+ 90 \cdot N\_b}{270}$$

Now each side contributes equally and independent of the number and size of triangles connected to the vertex.

**EDIT:**

I just realized, that the front face also contains only 2 triangles. The diagonal of the back face triangles irritated me. However, this will not affect the conclusion but the weigting factors change. For the fist approach you get:

$$N\_v = \frac{2\*N\_l + 1 \cdot N\_f + 1 \cdot N\_b}{4}$$

The second remains unchanged and for the angles you get:

$$N\_v = \frac{2\cdot 45 \cdot N\_l + 90 \cdot N\_f+ 90 \cdot N\_b}{270}$$

which is still correct. What is interesting is that both your approaches give the same results for the shown cube, since a connection of the vertex to 2 triangles also means that the area weight is doubled. You can also see this if you compare both pictures.

> **Comments:**
> **username_0**: Using the angle worked  

---

### Answer by username_3 on 2020-04-09. Score: 0

Assuming you want to calculate the *shared* vertex normal... if you know which faces use the vertex and they have unitised normals.

\begin{equation\*}\left \| \sum \left \| n\_{t} \right \| \right \|\end{equation\*}

Your first appraoch is close, but would only work if the face normals are unitised otherwise they will skew.

[See this question for more information](https://computergraphics.stackexchange.com/questions/4031/programmatically-generating-vertex-normals)

Given your last image, it looks like you want normals per face (flat shading) in which case you shouldn't share your vertices between faces, instead you need three vertices for each triangle (i.e 36 for a cube using tgriangles, or 24 for a cube if using quads).

If you want to use no more than 8 vertices, you will effectively get smooth shading (possibly what your first two images show) and not flat shading (what it looks like you want with your 3rd image), or you need to have normals per face (and not per vertex).

> **Comments:**
> **username_0**: That's just doing the area weighted average of the face normals, it's just going about it differently than I am  
> **username_3**: @username_0 the vertex normal has nothing to do with area. When you say *calculate normal*, what is it do you mean exacatly? Did you check out the qu I linked to.  
> **username_0**: I read the question you linked, what Inigo Quilez is doing is, he's adding the cross product then nromalizing the vertex, the cross product gives you  the normal times the area of the triangle times 2.  Then when you nromalize it, that;s equivalent to dividing by the norm, and the norm is equal to the sum of the areas of all trinagles times 2.  i.e the formula in the linked question is the same as averaging the face normals based on the area of the adjacent triangles.  
> **username_3**: @username_0 I see what you are saying, apologies my bad, you are looking for *face weighted* vertex normal rather than the vertex normal. This is not the correct normalisation to do for the topology you have then (i.e a cube, which has hard edges) and so not going to give you the answer you are looking for. Agree with username_2, you should weight the normals based on adjacent angle difference, and **not** area. The type of normalisation you wish to do depends on what you want it for (lighting, topology analysis etc), and the topology you have. What do you want the normal for?  
> **username_0**: I need the normal to do afine scaling  

---

