1

I'd like to use a python script to transfer normals to a new uv layer. Here is my first attempt:

import bpy

ob = bpy.context.object

for loop in ob.data.loops: normal = ob.data.vertices[loop.vertex_index].normal ob.data.uv_layers["XY"].data[loop.index].uv = (normal.x, normal.y) ob.data.uv_layers["ZW"].data[loop.index].uv = (normal.z, 0)

What I eventually want the script to be able to do is read custom split normals. I heard this was possible through the use of this script. The normal section underneath is supposed to calculate the normals using calc_normals_split or calc_tangents. However every time I try to incorporate this into my script I keep getting error messages or the result comes out as just one color. If anyone could help me to make it work would be much appreciated.

brockmann
  • 12,613
  • 4
  • 50
  • 93
  • your url points to the man page for MeshLoop, but there's no script there. Did you mean to point to an example? – Marty Fouts Oct 13 '21 at 20:12
  • 1
    Yeah, that's correct. After using ob.data.calc_normals_split() you access the normals with loop.normal. What error message are you getting? Make sure you are in object mode and not edit mode when you run the script. – scurest Oct 13 '21 at 23:34

1 Answers1

4

MeshLoop.normal

As commented by @scurest

After using ob.data.calc_normals_split() you access the normals with loop.normal. What error message are you getting? Make sure you are in object mode and not edit mode when you run the script.

Look at the loop normal, rather than the vertex normal to get the custom split normal values.

Test script, using foreach set to set the UV values rather than directly looping over them.

import bpy
import numpy as np

context = bpy.context

ob = context.object me = ob.data

get or create uv layers

xy_layer = me.uv_layers.get("XY") or me.uv_layers.new(name="XY") zw_layer = me.uv_layers.get("ZW") or me.uv_layers.new(name="ZW")

calc split nomrals

me.calc_normals_split()

norms = np.empty(3 * len(me.loops)) me.loops.foreach_get("normal", norms) nx, ny, nz = norms.reshape((-1, 3)).T nw = np.zeros(len(nz)) xy_layer.data.foreach_set("uv", np.array([nx, ny]).T.ravel()) zw_layer.data.foreach_set("uv", np.array([nz, nw]).T.ravel())

batFINGER
  • 84,216
  • 10
  • 108
  • 233
  • 1
    Here is what it looks like when I run the script and extract the uv coordinates in the shader editor https://ibb.co/T0szQtm and here is how it should look https://ibb.co/bFdCM3F I think something is going wrong when It transfers the normals to uv coordinates. – Abdurahman Pelletier Oct 14 '21 at 17:32
  • 1
    Whoops, Required a transpose before the ravel. – batFINGER Oct 15 '21 at 06:57