As far as I had some issues with guessing how to get this and I had found no solutions in google search results - I just leave it here (it may help someone).
Issue - getting normal via existing API functionality return normal without taking in to account object scale.
On image example - originally norlmal look at 45°, after scaling object by Z to 0.1 Blender still return same vector 0.0, -0,707, 0.707. Bmesh
.normal return same and samely has no option to return “true” normal.
Solution - it need to multuply normal vector values by scale vector values (next code work for 2.93)
import bpy, bmesh, mathutils bmd = bmesh.from_edit_mesh(bpy.context.edit_object.data) nrm = bmd.select_history.active.normal #Pick normal for active element. print('Normal' + str(nrm)) obm = bpy.context.object.matrix_world #Get object world matrix. obm_s = obm.decompose() #Get object scale from matrix. # Multiply each of normal vector values by two others from object scale vector (normal X * scale Y * scale Z) + normalize result. nrm_fixed = mathutils.Vector((nrm*obm_s*obm_s, nrm*obm_s*obm_s, nrm*obm_s*obm_s)).normalized() print('Normal fixed' + str(nrm_fixed))
If someone from devs staff or close to them read this - it would be nice to implement on API level some
.normal_scaled parameter to return this true normal vector without such cumbersome formulas.
.normal_world to return normal already adjusted by object rotation and object scale. It could be really handy for addon developers to just return normal vectors without necessity to multiply them first by ton of cumbersome stuff.