本日は Blender の技術調査枠です。
Blender2.8で利用可能なpythonスクリプトを作ります。
メッシュ頂点のXY座標を元にUVマップのUV座標を変更する
メッシュ頂点のXY座標を元にUVマップのUV座標を変更します。
指定のUVマップが存在しない場合は新規作成します。
オブジェクトの中心点とサイズを元にUVマップに収まるよう調整します。
・project_UVmap_xyposh.py
# bpyインポート import bpy # メッシュ操作のため import bmesh # オブジェクトのXY軸座標を元にUVマップを設定する def project_UVmap_xypos(arg_objectname="Default", arg_uvname="UVMap") -> bool: """オブジェクトのXY軸座標を元にUVマップを設定する Keyword Arguments: arg_objectname {str} -- 指定オブジェクト名 (default: {"Default"}) arg_uvname {str} -- 指定UVマップ名 (default: {"UVMap"}) Returns: bool -- 実行正否 """ # 指定オブジェクトを取得する # (get関数は対象が存在しない場合 None が返る) selectob = bpy.data.objects.get(arg_objectname) # 指定オブジェクトが存在するか確認する if selectob == None: # 指定オブジェクトが存在しない場合は処理しない return False # オブジェクトがメッシュであるか確認する if selectob.type != 'MESH': # 指定オブジェクトがメッシュでない場合は処理しない return False # 指定オブジェクトをアクティブに変更する bpy.context.view_layer.objects.active = selectob # 元々の操作モードを記録する befmode = bpy.context.active_object.mode # 編集モードに移行する bpy.ops.object.mode_set(mode='EDIT', toggle=False) # Bメッシュデータを取得する # Bメッシュアクセスのマニュアル # (https://docs.blender.org/api/current/bmesh.types.html?highlight=bmedge#bmesh.types.BMesh) bmeshdata = bmesh.from_edit_mesh(selectob.data) # UVレイヤーの参照を取得する # レイヤーアクセスのマニュアル # (https://docs.blender.org/api/current/bmesh.types.html#bmesh.types.BMLayerAccessLoop) targetuvlayer = bmeshdata.loops.layers.uv.get(arg_uvname) # 指定UVマップが存在するか確認する if targetuvlayer == None: # 指定UVマップが存在しない場合は新規作成する targetuvlayer = bmeshdata.loops.layers.uv.new(arg_uvname) # オブジェクトのバウンドボックスから中心点を計算する target_centerpos = get_object_center(arg_objectname=arg_objectname) # オブジェクトのサイズを取得する target_dimension = selectob.dimensions # X軸とY軸の長い方の辺の長さを取得する boundsize = 0.0 if (target_dimension[0] > target_dimension[1]): boundsize = target_dimension[0] else: boundsize = target_dimension[1] # メッシュの面の参照からUVマップの頂点を編集する # 面の参照を取得する # 面アクセスのマニュアル # (https://docs.blender.org/api/current/bmesh.types.html?highlight=bmedge#bmesh.types.BMFace) for face in bmeshdata.faces: # 要素の参照を取得する # 要素アクセスのマニュアル # (https://docs.blender.org/api/current/bmesh.types.html#bmesh.types.BMElemSeq) for loop in face.loops: # UVレイヤーの参照を取得する loop_uv = loop[targetuvlayer] # メッシュ頂点のXY座標を取得する uvpos_u = loop.vert.co.x uvpos_v = loop.vert.co.y # 中心点を使ってUV座標における原点位置(0,0)に補正する uvpos_u = uvpos_u - (target_centerpos[0] - (boundsize / 2.0)) uvpos_v = uvpos_v - (target_centerpos[1] - (boundsize / 2.0)) # UV座標の大きさ(1,1)に収まるよう調整する uvpos_u = uvpos_u / boundsize uvpos_v = uvpos_v / boundsize # 頂点のUV情報を取得する # UV情報アクセスのマニュアル # (https://docs.blender.org/api/current/bmesh.types.html#bmesh.types.BMLoopUV) loop_uv.uv[0] = uvpos_u loop_uv.uv[1] = uvpos_v # メッシュ情報を更新する bmesh.update_edit_mesh(selectob.data) # 変更前のモードに移行する bpy.ops.object.mode_set(mode=befmode) return True # オブジェクトのバウンドボックスから中心点を計算する def get_object_center(arg_objectname="Default") -> list: """オブジェクトのバウンドボックスから中心点を計算する Keyword Arguments: arg_objectname {str} -- 対象オブジェクト名 (default: {"Default"}) Returns: list -- 中心座標 """ # 指定オブジェクトを取得する # (get関数は対象が存在しない場合 None が返る) selectob = bpy.data.objects.get(arg_objectname) # 指定オブジェクトが存在するか確認する if selectob == None: # 指定オブジェクトが存在しない場合は処理しない return [0.0, 0.0, 0.0] # 指定オブジェクトの境界情報を取得する # オブジェクトのインタフェース # (https://docs.blender.org/api/current/bpy.types.Object.html) target_boundbox = selectob.bound_box # 変数の初期化 vertcount = 0 center_x = 0.0 center_y = 0.0 center_z = 0.0 # 頂点座標の加算 for vert_boundbox in target_boundbox: center_x += vert_boundbox[0] center_y += vert_boundbox[1] center_z += vert_boundbox[2] vertcount += 1 # 中点の計算 center_x = center_x / vertcount center_y = center_y / vertcount center_z = center_z / vertcount return [center_x, center_y, center_z] # 関数の実行例 project_UVmap_xypos(arg_objectname="Sphere", arg_uvname="UVMap")