UV Editor上で面や辺、頂点を操作する方法について学んだのでまとめておきます。

3D View上で要素を操作する場合と同じように、サイズや位置、回転を操作できるように実装しています。


動作確認環境 : Blender 4.2


UV Editor上で要素選択


3D View上で面、辺、頂点の要素をインデックスを用いて選択し、UVエディタ上で対応する要素を選択する処理を実装します。

▼element_select



3D View上では、初期設定により要素のインデックスが表示されますがUV Editor上には表示することができない?ので、3D Viewで選択した要素をUV Editor上に同期するような処理を行っています。

Python :
def uv_editor_element_select(
    element_list=[]
,   select_mode="FACE"
,   object_name_list=[]
):
    # UV Editorで全ての選択を解除
    bpy.ops.uv.select_all(action='DESELECT')
    
    # UV Sync Selection(選択の同期)を有効化
    bpy.context.scene.tool_settings.use_uv_select_sync = False

    # 3D Viewで要素選択
    element_select(
        element_list=element_list
    ,   select_mode=select_mode
    ,   object_name_list=object_name_list
    )

    # BMeshデータを取得
    bm = bmesh.from_edit_mesh(bpy.context.active_object.data)
    # UVレイヤーを取得
    uv_layer = bm.loops.layers.uv.active
    if uv_layer is None:
        print("UVレイヤーが見つかりません。")
        return

    # 3D Viewで選択された頂点やエッジ、面をUVに反映
    for face in bm.faces:
        if face.select:  # 3D Viewで選択された面
            for loop in face.loops:
                uv = loop[uv_layer]
                uv.select = True  # UV Editorで選択

    # メッシュの変更を更新
    bmesh.update_edit_mesh(bpy.context.active_object.data)

引数
  • element_list
    • 面、辺、頂点のインデックス指定
  • select_mode
    • 面:"FACE", 辺:"EDGE", 頂点:"VERT"
  • object_name_list
    • オブジェクト名

▼インデックスの表示設定



UV Editor上で移動/回転/拡大・縮小


UV_Editor上で要素を編集するための基本的な操作について実装していきます。

これらを用いると、イメージテクスチャを用いて画像を特定の面に適切に割り当てることが可能です。

選択要素の移動


選択した要素に対して要素の移動を行います。

Python :
def move_selected_uvs(offset_x, offset_y):
    obj = bpy.context.active_object
    
    # オブジェクトが存在し、メッシュであることを確認
    if obj is None or obj.type != 'MESH':
        print("アクティブなメッシュオブジェクトが必要です。")
        return
    
    # 編集モードに切り替え
    bpy.ops.object.mode_set(mode='EDIT')
    
    # BMeshデータを取得
    bm = bmesh.from_edit_mesh(obj.data)

    # UVレイヤーを取得
    uv_layer = bm.loops.layers.uv.active
    if uv_layer is None:
        print("UVレイヤーが見つかりません。")
        return
    
    # 選択されたUVを移動
    for face in bm.faces:
        for loop in face.loops:
            uv = loop[uv_layer]
            if uv.select:
                # UV座標を移動
                uv.uv.x += offset_x
                uv.uv.y += offset_y
    
    # メッシュの変更を反映
    bmesh.update_edit_mesh(obj.data)

2次元平面上の移動なので引数として
  • X軸の移動方向
  • Y軸の移動方向
を指定します。

選択要素の回転


選択した要素に対して回転を行います。

Python :
def rotate_selected_uvs(angle_degrees):
    obj = bpy.context.active_object
    
    # オブジェクトが存在し、メッシュであることを確認
    if obj is None or obj.type != 'MESH':
        print("アクティブなメッシュオブジェクトが必要です。")
        return
    
    # モード切り替え
    bpy.ops.object.mode_set(mode='EDIT')
    
    # BMeshデータを取得
    bm = bmesh.from_edit_mesh(obj.data)

    # UVレイヤーを取得
    uv_layer = bm.loops.layers.uv.active
    if uv_layer is None:
        print("UVレイヤーが見つかりません。")
        return
    
    # UV座標の中心を計算
    uv_coords = []
    for face in bm.faces:
        for loop in face.loops:
            uv = loop[uv_layer]
            if uv.select:
                uv_coords.append((uv.uv.x, uv.uv.y))
    
    if not uv_coords:
        print("選択されたUVがありません。")
        return
    
    center_x = sum([coord[0] for coord in uv_coords]) / len(uv_coords)
    center_y = sum([coord[1] for coord in uv_coords]) / len(uv_coords)
    
    # ラジアンに変換
    angle_radians = math.radians(angle_degrees)
    
    # 選択されたUVを回転
    for face in bm.faces:
        for loop in face.loops:
            uv = loop[uv_layer]
            if uv.select:
                # 中心からのオフセット
                dx = uv.uv.x - center_x
                dy = uv.uv.y - center_y
                # 回転行列適用
                uv.uv.x = center_x + (dx * math.cos(angle_radians) - dy * math.sin(angle_radians))
                uv.uv.y = center_y + (dx * math.sin(angle_radians) + dy * math.cos(angle_radians))
    
    # メッシュの変更を反映
    bmesh.update_edit_mesh(obj.data)

引数として、角度を指定します。

選択要素の拡大・縮小


選択した要素の拡大・縮小操作を行います。

Python :
def scale_selected_uvs(scale_x, scale_y):
    obj = bpy.context.active_object
    
    # オブジェクトが存在し、メッシュであることを確認
    if obj is None or obj.type != 'MESH':
        print("アクティブなメッシュオブジェクトが必要です。")
        return
    
    # 編集モードに切り替え
    bpy.ops.object.mode_set(mode='EDIT')
    
    # BMeshデータを取得
    bm = bmesh.from_edit_mesh(obj.data)

    # UVレイヤーを取得
    uv_layer = bm.loops.layers.uv.active
    if uv_layer is None:
        print("UVレイヤーが見つかりません。")
        return
    
    # UV座標の中心を計算
    uv_coords = []
    for face in bm.faces:
        for loop in face.loops:
            uv = loop[uv_layer]
            if uv.select:
                uv_coords.append((uv.uv.x, uv.uv.y))
    
    if not uv_coords:
        print("選択されたUVがありません。")
        return
    
    center_x = sum([coord[0] for coord in uv_coords]) / len(uv_coords)
    center_y = sum([coord[1] for coord in uv_coords]) / len(uv_coords)
    
    # 選択されたUVをスケーリング
    for face in bm.faces:
        for loop in face.loops:
            uv = loop[uv_layer]
            if uv.select:
                # UV座標を中心からスケーリング
                uv.uv.x = center_x + (uv.uv.x - center_x) * scale_x
                uv.uv.y = center_y + (uv.uv.y - center_y) * scale_y
    
    # メッシュの変更を反映
    bmesh.update_edit_mesh(obj.data)

引数として
  • X軸方向のスケーリング率
  • Y軸方向のスケーリング率
を指定します。


UV Editor Mirror投影


上下、左右に画像を反転する操作を実装します。

画像に文字列などを含む場合、方向を整える場合などに便利に使用することができます。

Python :
def mirror_selected_uvs(
        axis="X"
):
    obj = bpy.context.active_object
    
    # オブジェクトが存在し、メッシュであることを確認
    if obj is None or obj.type != 'MESH':
        print("アクティブなメッシュオブジェクトが必要です。")
        return
    
    # モード切り替え
    bpy.ops.object.mode_set(mode='EDIT')
    
    # BMeshデータを取得
    bm = bmesh.from_edit_mesh(obj.data)

    # UVレイヤーを取得
    uv_layer = bm.loops.layers.uv.active
    if uv_layer is None:
        print("UVレイヤーが見つかりません。")
        return
    
    # UV座標の中心を計算
    uv_coords = []
    for face in bm.faces:
        for loop in face.loops:
            uv = loop[uv_layer]
            if uv.select:
                uv_coords.append(uv.uv.x)
    
    if not uv_coords:
        print("選択されたUVがありません。")
        return
    
    if (axis == "X"):
        # UV座標のX軸の中心を計算
        center_x = sum(uv_coords) / len(uv_coords)
        
        # 選択されたUVをX軸でミラー
        for face in bm.faces:
            for loop in face.loops:
                uv = loop[uv_layer]
                if uv.select:
                    # 中心からのオフセットを反転
                    uv.uv.x = center_x - (uv.uv.x - center_x)
    else:
        # UV座標のY軸の中心を計算
        center_y = sum(uv_coords) / len(uv_coords)
        
        # 選択されたUVをY軸でミラー
        for face in bm.faces:
            for loop in face.loops:
                uv = loop[uv_layer]
                if uv.select:
                    # 中心からのオフセットを反転
                    uv.uv.y = center_y - (uv.uv.y - center_y)
    
    # メッシュの変更を反映
    bmesh.update_edit_mesh(obj.data)

引数として、X方向に反転するか、Y方向に反転するかを指定するためのkeyを指定します。



UV Editor操作の使用例


イメージテクスチャを用いて画像を取り込み、UV Editorを用いて画像を面に位置合わせする実装例を以下に示します。

Python :
# スクリプト名
script_text = bpy.context.space_data.text

# スクリプトのディレクトリを取得
script_dir = os.path.dirname(bpy.path.abspath(script_text.filepath))

def Base_create():
    bpy.ops.object.mode_set(mode='OBJECT')
    # 立方体を追加
    bpy.ops.mesh.primitive_cube_add(
        size=1
    ,   location=(0, 0, 1)
    ,   scale=(1,1,1)
    )
    # 名前設定
    bpy.context.object.name = "cube_00"

    # ベースマテリアル追加
    add_new_material(material_name="MT_cube_00")

    # Mode切り替え
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_mode(type='FACE')

    # 要素選択
    element_select(
        element_list=[0]
    ,   select_mode="FACE"
    ,   object_name_list=["cube_00"]
    )

    # マテリアル追加
    add_new_material(material_name="MT_cube_00_Content_00")

    # Mode切り替え
    bpy.ops.object.mode_set(mode='OBJECT')

    # イメージテクスチャ追加
    add_image_texture(
        material_name="MT_cube_00_Content_00"
    ,   image_path= script_dir + "/image.png"
    ,   texture_node_name="TX_Image_00"
    ,   node_location=(-400,300)
    )

    # テクスチャ追加
    add_new_texture(
        material_name="MT_cube_00_Content_00"
    ,   texture_name="ShaderNodeMix"
    ,   texture_node_name="Mix_RGB_00"
    ,   node_location=(-150, 600)
    ,   settings=[{"name": "data_type", "value": 'RGBA'}]
    )

    # ノードのリンク
    node_link_func(
        material_name="MT_cube_00_Content_00"
    ,   texture_node_name_out="Mix_RGB_00"
    ,   texture_node_name_in="Principled BSDF"
    ,   output_link="Result"
    ,   input_link="Base Color"
    )

    # ノードのリンク
    node_link_func(
        material_name="MT_cube_00_Content_00"
    ,   texture_node_name_out="TX_Image_00"
    ,   texture_node_name_in="Mix_RGB_00"
    ,   output_link="Color"
    ,   input_link="B"
    )

    # テクスチャ追加
    add_new_texture(
        material_name="MT_cube_00_Content_00"
    ,   texture_name="ShaderNodeMapping"
    ,   texture_node_name="Mapping_00"
    ,   node_location=(-600, 300)
    )

    # ノードのリンク
    node_link_func(
        material_name="MT_cube_00_Content_00"
    ,   texture_node_name_out="Mapping_00"
    ,   texture_node_name_in="TX_Image_00"
    ,   output_link="Vector"
    ,   input_link="Vector"
    )

    # テクスチャ追加
    add_new_texture(
        material_name="MT_cube_00_Content_00"
    ,   texture_name="ShaderNodeTexCoord"
    ,   texture_node_name="TX_Coord_00"
    ,   node_location=(-800, 300)
    )

    # ノードのリンク
    node_link_func(
        material_name="MT_cube_00_Content_00"
    ,   texture_node_name_out="TX_Coord_00"
    ,   texture_node_name_in="Mapping_00"
    ,   output_link="UV"
    ,   input_link="Vector"
    )

    # Mode切り替え
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_mode(type='FACE')

    # ------------------------------
    # マテリアル 画像の位置合わせ
    # ------------------------------
    
    # UV Editor 要素選択
    uv_editor_element_select(
        element_list=[0]
    ,   select_mode="FACE"
    ,   object_name_list=["cube_00"]
    )

    # UV Editor 移動
    move_selected_uvs(offset_x=0,offset_y=0.38)

    # UV Editor 拡大・縮小
    common_var=2.5
    scale_selected_uvs(scale_x=common_var, scale_y=common_var)

    # UV Editor 回転
    rotate_selected_uvs(angle_degrees=90)

    # Mirror 投影
    mirror_selected_uvs(axis="X")

▼add_new_material


▼add_new_texture
▼node_link_func



以上

このエントリーをはてなブックマークに追加
コメントを閉じる

コメント

コメントフォーム
記事の評価
  • リセット
  • リセット