Most efficient algorithm to calculate vertex normals from set of triangles for Gouraud shading

故事扮演 提交于 2019-11-28 04:53:50

问题


We are given a set of triangles. Each triangle is a triplet of points. Each point is a triplet of real numbers. We can calculate surface normal for each triangle. For Gouraud shading however, we need vertex normals. Therefore we have to visit each vertex and look at the triangles that share that vertex, average their surface normals and we get vertex normal.

What is the most efficient algorithm and data structure to achieve this?

A naive approach is this (pseudo python code):

MAP = dict()
for T in triangles:
  for V in T.vertices:
    key = hash(V)
    if MAP.has(key):
      MAP[key].append(T)
    else:
      MAP[key] = []
      MAP[key].append(T)

VNORMALS = dict()
for key in MAP.keys():
  VNORMALS[key] = avg([T.surface_normal for T in MAP[key]])

Is there a more efficient approach?


回答1:


Visit each triangle, calculate the normal for each triangle, ADD those to the vertex normal for each corner vertex.
Then at the end, normalise the normals for each vertex.

Then at least you only have to traverse the triangles once and you only store one normal/vertex.




回答2:


Each vertex belongs to one or more faces (usually triangles, sometimes quads -- I'll use triangles in this answer).

A triangle that is not attached to any other triangles cannot be 'smoothed'. It is flat. Only when a face has neighbours can you reason about smoothing them together.

For a vertex where multiple faces meet, calculate the normals for each of these faces. The cross product of two vectors returns a perpendicular (normal) vector, which is what we want.

A --- B
  \ /
   C

v1 = B - A
v2 = C - A
normal = v1 cross v2

Be careful to calculate these vectors consistently across all faces, otherwise your normal may be in a negative direction to that you require.

So at a vertex where multiple faces meet, sum the normals of the faces, normalise the resulting vector, and apply it to the vertex.

Sometimes you have a mesh where some parts of it are to be smoothed, and others not. An easy to picture example is a cylinder made of triangles. The round surface of the cylinder would smooth well, but if you consider triangles from the flat ends at the vertices around the sharp ridge, it will look strange. To avoid this, you can introduce a rule that ignore normals from faces which deviate too far from the normal of the face you're calculating for.

EDIT there's a really good video showing technique for calculating Gourad shading, though it doesn't discuss an actual algorithm.

You might like to take a look at the source of of Three.js. Specifically, the computeVertexNormals function. It does not support maintaining sharp edges. The efficiency of your algorithm depends to a large extent upon the way in which you are modelling your primitives.



来源:https://stackoverflow.com/questions/13205226/most-efficient-algorithm-to-calculate-vertex-normals-from-set-of-triangles-for-g

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!