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]
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.