I work on addon for UV box mapping. In my addon I need to check face normal to sort X,Y or Z oriented faces. By following this topic I found how to compensate object rotation by multiplying object matrix to face normal vector.

Now issue with object scale. On image - object scaled by Z to 0.1, face normal look almost straight to up to Z but mesh data still return normal as if object not scaled.

Question is - how to compensate object scale to get "true" face normals? Blender do it somehow under the hood when showing Normal Gizmo for selected face so how can I get same result.


Thanks batFINGER for help.

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.
obm = bpy.context.object.matrix_world       #Get object world matrix.

nrm_fixed = (obm.inverted_safe().transposed().to_3x3() @ nrm).normalized()
  • 1
    $\begingroup$ I take it the quest here is to find the global space normal. See blender.stackexchange.com/questions/27491/… Edited a test script into my answer to add an empty as a "global normal" display. Couldn't get a result using nrm_fixed as above. $\endgroup$
    – batFINGER
    Jul 29 at 19:18
  • $\begingroup$ Formula I have posted only compensate object scale. If object has also rotation u need first compensate scale then rotation by multiply result with matrix_world.to_3x3().normalized() ( .to_3x3() - removed location .normalized() - removed scale) Not sure I get it right "I take it the quest here is to find the global space normal." I have checked your link... so u propose just use mw.inverted_safe().transposed().to_3x3()? Check this screenshot - my final vector look at (1.0000, 0.0009, 0.0006), your one at (0.8581, -0.3095, -0.4098) what looks wrong. $\endgroup$
    Jul 31 at 5:57
  • $\begingroup$ Now it become interesting for me - on your GIF empties looks placed perfectly correct along the normals. I not sure but it looks like because you don't use .normalized() (so you get actually scaled normal vector) this n.to_track_quat().to_euler() you use to set empties rotation take in to account that normal scale and set correct euler rotation. Interestingly... But still not work for me - I need clear normalized and correct face normal vector for my addon purpose. $\endgroup$
    Jul 31 at 6:20
  • $\begingroup$ OMG - I just realized that (object.matrix_world.inverted_safe().transposed().to_3x3() @ normal).normalized() return same (1.0000, 0.0009, 0.0006) normal vector. Thank you kindly for your help )) $\endgroup$
    Jul 31 at 7:16

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.