# Python: vertex normal according to World

If i get a normal of a vertex - i'll get it in local coordinates. For example:

bpy.context.object.data.vertices.normal


If an object will have rotation or scale - normal direction will be incorrect according to world orientation. How to convert the vertex normal according to the world?

Actually it is, when the scaling factors are not the same (as @mifth pointed out) :

normal_local = C.object.data.vertices.normal.to_4d()
normal_local.w = 0
normal_local = (C.object.matrix_world * normal_local).to_3d()


If you know they are all the same, you can use :

C.object.rotation_euler.to_matrix() * C.object.data.vertices.normal


Cheers,

• yes, that's corect. the only problem - if object is scaled non-proportionaly (like (0.1, 0.5, 0.7)) it will make incorrect normal direction too. – mifth Jul 3 '15 at 8:13
• It takes rotation but it does not take scale now. Possibly there should be adifferent solution. :( Sorry. – mifth Jul 6 '15 at 20:28
• The solution above gives the normal the correct direction. I don't understand how you want the scale to be taken into account for the normal. Maybe you can scale the normal by the mean of the 3 scale factors, would that be what you want ? – Jonathan Chemla Jul 8 '15 at 5:07
• Sorry for late response. Here is what i want to say i.imgur.com/WPpUp5B.png If scale will be different - normals will have different direction. – mifth Jul 14 '15 at 11:35

I've run into this problem many times, I always have to search for the answer. But I use the tranpose of the inverse of the world_matrix to get the world normal.

https://computergraphics.stackexchange.com/questions/1502/why-is-the-transposed-inverse-of-the-model-view-matrix-used-to-transform-the-nor

mx_inv = C.object.matrix_world.inverted()
mx_norm = mx_inv.transposed().to_3x3()

world_no = mx_norm * C.object.data.vertices.normal


you have to multiply it with the world matrix (the order matters! Matrix first) :

C.object.matrix_world * C.object.data.vertices.normal

• Shouldn't the matrix be first in the multiplication? – nantille Sep 25 '18 at 9:46
• @natille not sure how the math goes here, you can edit the post if you think it's wrong. – Chebhou Sep 25 '18 at 16:22

"Brute Strength" Approach

Knowing that any coordinate in local space can be converted to global space using the object's matrix world. Can get the local coordinate of the end of the normal by using it against the local origin (0, 0, 0) where adding normal is also its local coordinate. Converting each end to global and subtracting will produce desired direction vector in global space.

It is normalized to have length 1 in global space.

mw = ob.matrix_world
# v is some vertex
global_norm = (mw @ v.normal - mw @ Vector()).normalized()


Note, mw * Vector() is the global location of mesh origin, which is also mw.to_translation()

My linear algebra is a bit rusty, re a proof, , from experience its often the case that multiplying the mw by the local normal (mw @ v.normal) doesn't always produce the same result if the global origin is not local origin.

PS updated for 2.8 to use @ for matrix vector multiplication.

• Do you think we should already answer Python questions assuming Blender 2.80? It is still not released, would it not make sense to assume people do not yet use it for work? – Martynas Žiemys Jan 10 '19 at 12:00
• It's quite ad hoc This one came up from another question, needed an edit, so I updated for 2.8, rather than wait for a more sensible moment in time – batFINGER Jan 10 '19 at 12:09
• I suppose that makes sense. I was just wondering how to approach this when answering other questions. I'll probably start including comments for changes in 2.80 with answers for 2.79. – Martynas Žiemys Jan 10 '19 at 12:25