アストラルプリズム

PC、スマホ、ゲームなどの備忘録と日記

Blender python 指定した辺をUVテクスチャの下方向にする

指定した辺をUVテクスチャの下方向にする。
ただしオブジェクトは一枚の板ポリの場合

import bpy,bmesh
from mathutils import Matrix
#指定した辺(ループ)
loop_no = 5

plane = bpy.context.object
msh = plane.data
p_mat = plane.matrix_world.copy()
norm = msh.polygons[0].normal
mx_inv = p_mat.inverted()
mx_norm = mx_inv.transposed().to_3x3()
world_norm = mx_norm @ norm
world_norm.normalize()

vertex_no = msh.loops[loop_no].vertex_index
muki0 = p_mat @ msh.vertices[vertex_no].co
if loop_no + 1 == len(msh.loops):
    muki1 = p_mat @ msh.vertices[msh.loops[0].vertex_index].co
else:
    muki1 = p_mat @ msh.vertices[msh.loops[loop_no +
                                                1].vertex_index].co
 
muki = (muki1 - muki0).normalized()

cro = muki.cross(world_norm).normalized()
loc = plane.location
         
m = Matrix([[muki.x,-cro.x, world_norm.x, loc.x],
            [muki.y,-cro.y, world_norm.y, loc.y],
            [muki.z,-cro.z, world_norm.z, loc.z], [0, 0, 0, 1]])
            
new_mat = m.inverted() @ p_mat 
   
uv_p = []
#指定した辺を下にした時の頂点座標をグローバル値でとる
for l in msh.loops:
    p = new_mat @ msh.vertices[l.vertex_index].co
    uv_p.append([p.x,p.y])
    
max_x = max(b[0] for b in uv_p)
min_x = min(b[0] for b in uv_p)
dif_x = abs(max_x-min_x)
max_y = max(b[1] for b in uv_p)
min_y = min(b[1] for b in uv_p)
dif_y = abs(max_y - min_y)
for p in uv_p:
    p[0] = (p[0]-min_x)/dif_x
    p[1] = (p[1]-min_y)/dif_y
    
bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(msh)
bm.faces.ensure_lookup_table()
uv_layer = bm.loops.layers.uv.active

for v in bm.faces[0].loops:
    v[uv_layer].uv = uv_p[v.index]
bmesh.update_edit_mesh(msh)
bpy.ops.object.mode_set(mode='OBJECT')