2025年4月27日日曜日

3D座標付き遺物リストのプロット用Blenderアドオン自作

 I made a Blender addon for plotting a list of relics with 3D coordinates


I made a Blender addon that plots a list of relics with 3D coordinates in Blender3D space. Until now I've been doing this with BlenderPython, but it's much more convenient to make it an addon. I was able to create the addon quickly with ChatGPT support.


3D座標付き遺物リストをBlender3D空間にプロットするBlenderアドオンを自作しました。これまではBlenderPythonで行ってきましたが、アドオンにした方がはるかに便利です。アドオン作成はChatGPT支援で直ぐにできました。

1 3D座標付き遺物リストのプロット用Blenderアドオン CSV Tools


3D座標付き遺物リストのプロット用Blenderアドオンの機能

csvファイルは単純に次の形式としました。

ID,X,Y,Z,TYPE

1,0,0,0,a

2,2,3,1,b

3,5,-2,4,c

csvファイルを選択できるようにしたので、便利です。

ID名(遺物名)のオブジェクトを作成し、TYPE名のコレクションに格納するので、多数遺物の扱いがしやすくなっています。

オブジェクトは0.05m×0.05m×0.05mのCUBEとして設定してあります。

アドオンづくりの楽しみという観点から言えば、色塗りを付加したり、オブジェクトの大きさや形状を変えたりといろいろ工夫はできるのですが、それらの機能を付加すると、自分の作業ではかえって煩雑になるので、それらからは試したうえで、撤退しました。

プロットしたものをgeometry nodesで凝った装飾を加える方が手軽で、自由で、効率的です。最初にプロットしたものに対して非破壊的にできます。

このアドオン作成はChatGPTの支援を受けました。

2 参考 自作アドオンのPythonスクリプト

以下のスクリプトをテキストファイルにして、拡張子をtxtからpyに変更するとPythonスクリプトになります。そのPythonスクリプトをBlenderアドオンとして読み込むと、アドオンCSV Toolsが使えるようになります。

bl_info = {
    "name": "CSVからCUBE配置ツール",
    "author": "ChatGPTアシスト",
    "version": (1, 1),
    "blender": (3, 0, 0),
    "location": "3Dビュー > サイドバー > CSV Tools",
    "description": "CSVファイルの座標にCUBEを配置し、TYPEごとにコレクションに整理するツール (ファイル選択対応)",
    "category": "Object",
}

import bpy
import csv
from bpy.props import StringProperty
from bpy_extras.io_utils import ImportHelper
from bpy.types import Operator, Panel

# --- CSVからCUBEを配置するメイン処理 ---
def get_or_create_collection(name):
    if name in bpy.data.collections:
        return bpy.data.collections[name]
    else:
        new_collection = bpy.data.collections.new(name)
        bpy.context.scene.collection.children.link(new_collection)
        return new_collection

def create_cubes_from_csv(csv_file):
    with open(csv_file, newline='', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            x = float(row['X'])
            y = float(row['Y'])
            z = float(row['Z'])
            type_name = row['TYPE']
            
            # Cube作成
            bpy.ops.mesh.primitive_cube_add(size=1, location=(x, y, z))
            obj = bpy.context.active_object
            obj.scale = (0.05, 0.05, 0.05)
            obj.name = f"Artifact_{row['ID']}"

            # 適切なコレクションに移動
            collection = get_or_create_collection(type_name)
            collection.objects.link(obj)
            bpy.context.scene.collection.objects.unlink(obj)

# --- オペレータークラス ---
class OBJECT_OT_import_csv_create_cubes(Operator, ImportHelper):
    bl_idname = "object.import_csv_create_cubes"
    bl_label = "CSVを読み込んでCUBEを配置"
    bl_options = {'REGISTER', 'UNDO'}

    filename_ext = ".csv"
    filter_glob: StringProperty(
        default="*.csv",
        options={'HIDDEN'},
    )

    def execute(self, context):
        create_cubes_from_csv(self.filepath)
        return {'FINISHED'}

# --- パネルクラス ---
class VIEW3D_PT_csv_tools(Panel):
    bl_label = "CSV Tools"
    bl_idname = "VIEW3D_PT_csv_tools"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'CSV Tools'

    def draw(self, context):
        layout = self.layout
        layout.operator(OBJECT_OT_import_csv_create_cubes.bl_idname, text="CSVファイルを選択して配置")

# --- 登録処理 ---
classes = (
    OBJECT_OT_import_csv_create_cubes,
    VIEW3D_PT_csv_tools,
)

def register():
    for cls in classes:
        bpy.utils.register_class(cls)

def unregister():
    for cls in reversed(classes):
        bpy.utils.unregister_class(cls)

if __name__ == "__main__":
    register()

0 件のコメント:

コメントを投稿