夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

Blenderでオブジェクトからカスタム分割法線を一括でクリアするスクリプトを書く

本日はBlenderモデリング枠です。

本日はUnityや他の3Dツールなどで作成した3DモデルをBlenderで編集する際などに問題となるカスタム分割法線を一括でクリアしていきます。

〇カスタム分割法線とは?

カスタム分割法線とは3Dモデルが持つことができる法線を一括でスムースをかけるのではなく頂点ごとにカスタマイズすることです。

 通常、メッシュオブジェクトは頂点ごとに面の垂直方向を表すベクトルとして法線(Normal)を持ちます。

カスタム分割法線を使用することで、各頂点ごとに面ごとの法線情報を持つことができるようにすることができます。これにより、面の境界での法線の制御が容易になります。

 カスタム分割法線を使用すると、メッシュを滑らかな曲面とハードエッジが混在するような外観にすることができます。

 しかし冒頭で述べた通りUnityなどでfbxエクスぷーたーなどを使用してエクスポートしたモデルをBlenderでインポートすると次のように法線が崩れてしまうことがあります。

 これを修正するためにはカスタム分割法線を一度clearにする必要がありますが、オブジェクトごとに行っていては作業が大変です。また、どのオブジェクトがカスタム分割法線を使用しているかを判断するのも手間がかかってしまいます。

今回はスクリプトでカスタム分割法線をクリアにしていきます。

〇スクリプトでカスタム分割法線をクリアにする

選択しているオブジェクトの持つカスタム分割法線をクリアするためには次のスクリプトを実行します。

#Blender用のライブラリ
import bpy

# 現在のシーンを取得
scene = bpy.context.scene

# 現在選択されているオブジェクトを取得
selected_objects = bpy.context.selected_objects

# 選択されたオブジェクトごとに処理を行う
for obj in selected_objects:
    # オブジェクトがメッシュでない場合はスキップ
    if obj.type != 'MESH':
        continue

    # メッシュを取得
    mesh = obj.data

    # オブジェクトがカスタム分割法線データを持っている場合はクリアする
    if hasattr(mesh, 'has_custom_normals') and mesh.has_custom_normals:
        bpy.ops.mesh.customdata_custom_splitnormals_clear()

        # メッシュの更新
        mesh.update()

# ビューポートをリフレッシュ
bpy.context.view_layer.update()

bpy.ops.mesh.customdata_custom_splitnormals_clear()を使用することでカスタム分割法線をクリアできます。

一つ一つ実行していては手間は変わらないので、シーン内のオブジェクトすべてに対して実行するスクリプトは以下になります。

import bpy

# 現在のシーンを取得
scene = bpy.context.scene

# シーン内のすべてのオブジェクトを取得
all_objects = bpy.data.objects

# シーン内のすべてのオブジェクトに対して処理を行う
for obj in all_objects:
    # オブジェクトがメッシュでない場合はスキップ
    if obj.type != 'MESH':
        continue

    # メッシュを取得
    mesh = obj.data

    # オブジェクトがカスタム分割法線データを持っている場合はクリアする
    if hasattr(mesh, 'has_custom_normals') and mesh.has_custom_normals:
        bpy.ops.mesh.customdata_custom_splitnormals_clear()

        # メッシュの更新
        mesh.update()

# ビューポートをリフレッシュ
bpy.context.view_layer.update()

これを実行すると次のように法線がクリアされます。

本日は以上です。