8
$\begingroup$

I'm working with Kinect face api, it provides an array of vertices and indices for triangles which is to be rendered to make the face image.

The no of vertices and their order in array as well as the indices given by kinect is always constant.

However the api gives no information on UV data and vertex normals.

The application requires me to keep the vertex order as given out by the kinect as their positions in 3d space change as per facial movement so generating uv and normals in a 3d editing software is out of question.

I managed to generate UV by projecting the vertex positions onto a 2D plane since there were very few vertices on same plane.

However, I don't know how to generate vertex normals for the mesh, without vertex normal the face mesh draws with no depth of its features from prespective, although silhouette is visible as vertex positions are correct.

I understand that due to absence of vertex normals the lighting wont work correctly on it and hence the pale featureless mesh it looks right now.

so how do I generate vertex normals when all I have is just vertex position and the index of vertices to make triangles out of it?

$\endgroup$
  • $\begingroup$ n = (v1 - v0) x (v2 - v0), where v0, v1, and v2 are the vertices of the (triangle) face in question. The order is importan. Normalize it if you really need to. (and x is cross product) $\endgroup$ – 3Dave Oct 5 '16 at 23:17
11
$\begingroup$

Computing the normal from vertex positions is quite simple using the vector cross product.

The cross product of two vectors $u$ and $v$ (noted $u \times v$, or sometimes $u \wedge v$) is a vector perpendicular to $u$ and $v$, of length $||u \times v|| = ||u|| \cdot ||v|| sin(\theta)$, with $\theta$ the angle between $u$ and $v$. The direction of the vector will depend on the order of the multiplication: $u \times v$ is the opposite of $v \times u$ (the two directions perpendicular to the plane).

If you are not familiar with the cross product, I invite you to read about it and get comfortable with it. Normals will then seem simple.

Flat shading normals

If you have a triangle $ABC$, $AB \times AC$ is a vector perpendicular to the triangle and with a length proportional to its area. Since the normal is the unit vector perpendicular to the triangle's plane, you can get the normal with:

$N = \dfrac{AB \times AC}{||AB \times AC||}$

In code, this would look like n = normalize(cross(b-a, c-a)) for example. Just apply this over all your faces and you will have your normals per face.

For each triangle ABC
    n := normalize(cross(B-A, C-A))
    A.n := n
    B.n := n
    C.n := n

Note that this assumes vertices are not shared between triangles. I am not familiar with the Kinect API; it's quite possible that they are shared, in which case you would have to duplicate them, or move on to the next solution:

Smooth shading normals

After lighting with normals computed as above, you will notice that triangle edges are apparent. If this in not desirable, you can compute smooth normals instead, by taking into account all the faces that share a same vertex.

The idea is that if a same vertex is shared by three triangles $T1$, $T2$ and $T3$ for example, the normal $N$ will be the average of $N1$, $N2$ and $N3$. Moreover, if $T1$ is a big triangle and $T2$ is a tiny one, you probably want $N$ to be more influenced by $N1$ than by $N2$.

Remember how the cross product is proportional to the area? If you add up the cross products then normalize the sum, it will do exactly the weighted sum we want. So the algorithm becomes:

For each vertex
    vertex.n := (0, 0, 0)

For each triangle ABC
    // compute the cross product and add it to each vertex
    p := cross(B-A, C-A)
    A.n += p
    B.n += p
    C.n += p

For each vertex
    vertex.n := normalize(vertex.n)

This technique is explained in longer detail this article by Iñigo Quilez: clever normalization of a mesh.


For more on normals, see also:

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.