How to calculate vertex normal

I need to set the vertex normals on a mesh. I have a procedrally generated terrain and I need to set the vertex normals after the mesh is displaced so that it does not look flat. Can anyone point me to a formula or anything like that to do it? I know the vertex normal has to be a vector in the form vert.normal = [x,y,z]

https://www.blender.org/api/blender_python_api_2_78_release/bge.types.KX_VertexProxy.html#bge.types.KX_VertexProxy

It’s called ‘normal’ like you have it. Hope that helps.

EDIT: Oh, and you can look at this for assigning vertex normals:
https://www.blender.org/api/blender_python_api_2_78_release/bge.types.KX_MeshProxy.html#bge.types.KX_MeshProxy
(it’s in the example code)

if you are joining many meshes at the seams, it’s helpful to use a kd tree,

you get each faces normal, and then average the overlapping faces normal

that is what I did for this

If you want flat faces the normals of all vertices of a face are the same -> face normal. The face normal is the cross product of two of the edges of the face.

f = face
v1,v2,v3,v4 = vertices

fn = face normal
vn1, vn2, vn3, vn4 = vertex normals

fn = (v1-v2).cross(v2-v3)

[remark: if you want the opposite normal - exchange the vectors]

Flat:

vn1 = vn2 = vn3 = vn4 = fn

smooth, means the vertex normal equals the vertex normals of the adjacent vertices of connected faces.

A) identify the adjacent vertices (of different faces) f1v, f2v, f3v, …;
B) I suggest tu calculate the average middle of the face normals normals, by adding them and normalize the result:

f1vn, f2vn, f3vn, ... = (f1vn + f2vn +f3vn + ... ).normalized()

I hope this helps

I’m having this problem as well, where I have a subdivided plane with 1600 triangles, a code that makes random vertices move randomly up and down, but the shading is flat. I need to update the normals. I already had a working code, but the shading looked a bit weird.

import mathutils

mesh = own.meshes[0] #first mesh


number = mesh.numPolygons #total number of polygons


for polyID in range(0, number): 
    
    p = mesh.getPolygon(polyID)
    
    a1 = mesh.getVertex(0, p.v1) #first vertex of polygon
    b1 = a1.getXYZ()
    a2 = mesh.getVertex(0, p.v2) #second vertex of polygon
    b2 = a2.getXYZ()
    a3 = mesh.getVertex(0, p.v3) #third vertex of polygon
    b3 = a3.getXYZ()
    
                        
    poly_n = mathutils.geometry.normal(b1,b2,b3)
    
    v_list = [a1, a2, a3]
       
    for v in v_list:    
                
        v.setNormal(poly_n)

But as you can see the darker areas are on vertices, not whole polygons, and I would like flat shaded type.
Sorry if I interrupted this thread but I didn’t want to start a new one if this one was on the same exact topic.

Attachments


def recalc_normals(cont):	
	mat_id = bge.texture.materialID(own, "MA"+"Material")
	for poly_id in range(mesh.numPolygons):
		poly = mesh.getPolygon(poly_id)
		v1 = mesh.getVertex(mat_id, poly.v1)
		v2 = mesh.getVertex(mat_id, poly.v2)
		v3 = mesh.getVertex(mat_id, poly.v3)
		if poly.v4 == 0:
			normal = mathutils.geometry.normal(v1.getXYZ(), v2.getXYZ(), v3.getXYZ())
			v1.setNormal(normal)
			v2.setNormal(normal)
			v3.setNormal(normal)
		else:
			v4 = mesh.getVertex(mat_id, poly.v4)
			normal = mathutils.geometry.normal(v1.getXYZ(), v2.getXYZ(), v3.getXYZ(), v4.getXYZ())

Here is the correct code.

With kdtree, I use 1 mesh in a couple thousand times, and use the kdtree to get all vertex that share a x/y/z cord and then you can average faces across objects.