見出し画像

【Blender】Pythonスクリプトでオブジェクトの作成や配置を行ってみる

KuMA Advent Calendar 2023 18日目の記事です.

BlenderでPythonスクリプトが使えるということは以前から知っていたのですが,使ったことがなかったので,ChatGPTに教えてもらいながら使ってみました.

使ったBlenderバージョンは2.83です.

Layout, Modelingとかのタブの一番右に「Scripting」がありました.いつも見てるのに知らなかったw

Scriptingタブの場所

ChatGPTに書いてもらった,Cubeを2つ配置するシンプルなスクリプトです.新規→プログラムを入力して,実行ボタンを押してみます.

import bpy
from math import radians

# 新しいオブジェクトを作成して配置する関数
def create_object(name, location):
    bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False, align='WORLD', location=location)
    obj = bpy.context.active_object
    obj.name = name
    return obj

# オブジェクトの作成と配置
obj1 = create_object("Cube1", (0, 0, 0))
obj2 = create_object("Cube2", (3, 3, 3))

# オブジェクトの回転
obj2.rotation_euler = (radians(45), radians(45), radians(45))

無事,オブジェクトをシーンに追加できました.

Cubeを配置できた!

次は,星形を作ってみます.

import bpy
import bmesh
from math import sin, cos, pi

def create_star(name, radius_outer, radius_inner, num_points, location=(0,0,0)):
    # 星のメッシュとオブジェクトを生成
    mesh = bpy.data.meshes.new(name)
    star_object = bpy.data.objects.new(name, mesh)

    # オブジェクトをシーンにリンク
    bpy.context.collection.objects.link(star_object)
    bpy.context.view_layer.objects.active = star_object
    star_object.select_set(True)

    # メッシュの編集を開始
    bm = bmesh.new()

    # 星の頂点を生成
    for i in range(num_points * 2):
        angle = i * pi / num_points
        if i % 2 == 0:
            # 外側の頂点
            vert = bm.verts.new((cos(angle) * radius_outer, sin(angle) * radius_outer, 0))
        else:
            # 内側の頂点
            vert = bm.verts.new((cos(angle) * radius_inner, sin(angle) * radius_inner, 0))

    # 頂点のルックアップテーブルを更新
    bm.verts.ensure_lookup_table()

    # 頂点をエッジで接続
    for i in range(len(bm.verts)):
        bm.edges.new((bm.verts[i], bm.verts[(i+1) % len(bm.verts)]))

    # メッシュを閉じるためのフェイスを作成
    bm.faces.new(bm.verts)

    # メッシュを更新して頂点とエッジを確定
    bm.to_mesh(mesh)
    bm.free()

    # オブジェクトを移動
    star_object.location = location

# 星の設定
name = "Star"
radius_outer = 1.0  # 外側の半径
radius_inner = 0.5  # 内側の半径(外側の半径の約半分)
num_points = 5      # 星の角の数
location = (0, 0, 0)  # 配置する場所

# 星を生成
create_star(name, radius_outer, radius_inner, num_points, location)

良い感じにできました.
こういう幾何学的な図形は,プログラムでも表現しやすくて,ChatGPTも得意そうです.

星形を作成できた!


最後に,シーン中のオブジェクトをいじってみます.

前に作ったパピモッチを,たくさん増やすスクリプトをかいてもらいました.

パピモッチ

すでにある「Body」というオブジェクトを取得して,XY平面上にランダムに15個配置するスクリプトです.

import bpy
import random

# 既存の「Body」という名前のオブジェクトを取得
original_body = bpy.data.objects.get('Body')

# オブジェクトが見つからない場合は終了
if not original_body:
    print("There is no object named 'Body' in the scene.")
else:
    # 配置したいオブジェクトの数
    number_of_copies = 15  # 必要な数に応じて変更してください

    # 配置する範囲の指定(1メートル四方のスペースを考慮)
    range_x = (-5, 5)
    range_y = (-5, 5)
    spacing = 0.5  # オブジェクト間の最小距離

    # コピーを配置する前にリストを初期化
    positions = []

    # オブジェクトを指定された数だけコピーして配置
    for i in range(number_of_copies):
        attempt = 0
        while attempt < 100:
            # ランダムな位置を生成
            loc_x = random.uniform(range_x[0] + spacing, range_x[1] - spacing)
            loc_y = random.uniform(range_y[0] + spacing, range_y[1] - spacing)
            loc_z = 0  # xy平面上に配置するため、z座標は0に
            position = (loc_x, loc_y, loc_z)

            # 他のオブジェクトと重ならないかをチェック
            if all([((loc_x - pos[0])**2 + (loc_y - pos[1])**2)**0.5 > spacing for pos in positions]):
                positions.append(position)

                # オリジナルのオブジェクトをコピー
                new_body = original_body.copy()
                new_body.data = original_body.data.copy()
                new_body.location = position

                # Z軸に沿ったランダムな回転を加える
                random_angle = random.uniform(0, 360)
                new_body.rotation_euler[2] = random_angle

                # 新しいオブジェクトをシーンにリンク
                bpy.context.collection.objects.link(new_body)
                
                break  # 位置が決まったら次のオブジェクトに移る
            attempt += 1

    # オリジナルのオブジェクトは非表示にするか、必要に応じて削除
    original_body.hide_viewport = True
    original_body.hide_render = True

# 必要であれば、シーンを更新
bpy.context.view_layer.update()

実行したら,良い感じに配置できました!
パピモッチがたくさんでかわいいです.

かわいい~

大分満足したので,これで終わります.
前からBlenderのスクリプトを触ってみたかったので,試せてよかったです.
結構簡単で楽しかったです.

モデリングするときにスクリプトを上手に使えると,制作がはかどりそうだなと思いました.

ここまで読んでいただきありがとうございました.

いただいたお金は書籍やお寿司の購入などに充てさせていただきます。