Open6

[メモ]blender python apiを使ったクリエイティブコーディングの練習

からくれ178からくれ178

ランダムに立方体配置

ランダムに立方体を配置する。

import bpy
import os
import sys
import argparse
import addon_utils
import random

# 立方体のサイズ
cube_size = 1.0

# 生成する立方体の数
num_cubes = 10

# ランダムな位置と回転を取得するための関数
def get_random_transform():
    # 位置
    location = (
        random.uniform(-10.0, 10.0),
        random.uniform(-10.0, 10.0),
        random.uniform(-10.0, 10.0),
    )

    # 回転
    rotation = (
        random.uniform(-180.0, 180.0),
        random.uniform(-180.0, 180.0),
        random.uniform(-180.0, 180.0),
    )

    return location, rotation

# 立方体を生成する
for i in range(num_cubes):
    # ランダムな位置と回転を取得
    location, rotation = get_random_transform()

    # 立方体を作成
    bpy.ops.mesh.primitive_cube_add(size=cube_size, location=location, rotation=rotation)

# オブジェクトを選択
bpy.ops.object.select_all(action='SELECT')

# ビューポートを更新
bpy.context.view_layer.update()

ランダムに生成するときはimport randomしないとエラー。
bpy.ops.mesh.primitive_cube_add関数でメッシュを新規作成できる。
https://docs.blender.org/api/3.6/bpy.ops.mesh.html#bpy.ops.mesh.primitive_cube_add

からくれ178からくれ178

アニメーションを自動作成したい

先ほど作成したランダムな立方体をつかって、アニメーションのキーフレームを自動で生成してほしい。

import bpy

#目標の座標を指定する
positions =  ((0, 3, 2), (4, 1, 6), (3, -5, 1), (3, 10, 1), (1, 8, 1))
#(0,3,2),(4,1,6),(3,-5,1),(3,10,1),(1,8,1)
#開始時の座標を指定する
start_pos = (0,0,0)


#変数obに3D viewportにあるオブジェクトを代入する
#ob = bpy.data.objects["Cube"]のようにして特定のものを動かすことも可能
def set_frame(ob):
    #開始のフレームを指定する
    frame_num = 0
    
    #目標の座標に移動する処理を繰り返す
    for p in positions:
        #開始のフレームを設定する
        bpy.context.scene.frame_set(frame_num)
    
        #変数locationに目標の座標の値を代入する
        ob.location = p
    
        #キーフレームの挿入を行う
        ob.keyframe_insert(data_path = "location",index = -1)
        #フレームを20ずらす
        frame_num += 20

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

# オブジェクトをループ処理
for obj in objects:
    # オブジェクトの種類が立方体の場合は選択
    if obj.type == 'MESH' :#$and re.search(r'Cube$', obj.name):
        ob = bpy.data.objects[obj.name]
        set_frame(ob)

なんでか知らないが、re.searchを使ったパターンはうまくいかなかった。
今回は立方体しかmeshがないのでいったんこれで進める。

アニメーションの作成参考:
https://qiita.com/masterkeaton12/items/a6dcfa160f2bb6bc2851

からくれ178からくれ178

立方体の自動配置からキーフレーム自動生成まで

クリエイティブコーディングをしたい。
グリッド上に立方体を配置してサインカーブで上下させたい。

import bpy
import math

def frame_scale():
    # シーン内のすべてのオブジェクトを取得
    objects = bpy.data.objects

    # オブジェクトをループ処理
    count = 0
    for obj in objects:
        # オブジェクトの種類が立方体の場合は選択
        if obj.type == 'MESH':
            ob = bpy.data.objects[obj.name]
            set_frame(ob,count)
            count += 1

#変数obに3D viewportにあるオブジェクトを代入する
#ob = bpy.data.objects["Cube"]のようにして特定のものを動かすことも可能
def set_frame(ob,count):
    #開始のフレームを指定する
    frame_num = 0
    
    positions = [(ob.location.x, ob.location.y, math.sin(n+count)) for n in range(12)]
    
    #目標の座標に移動する処理を繰り返す
    for p in positions:
        #開始のフレームを設定する
        bpy.context.scene.frame_set(frame_num)
    
        #変数locationに目標の座標の値を代入する
        ob.location = p
    
        #キーフレームの挿入を行う
        ob.keyframe_insert(data_path = "location",index = -1)
        #フレームを20ずらす
        frame_num += 20

def cube_add():
    num = 10
    # 立方体を生成する
    for i in range(num):
        for j in range(num):
            location = (i+0.5*i,j+0.5*j,0)
            rotation = (0,0,0)
                        
            # 立方体を作成
            bpy.ops.mesh.primitive_cube_add(size=1.0, location=location, rotation=rotation)

cube_add()
frame_scale()

とりあえずできた。

からくれ178からくれ178

ランダムにオブジェクトにカラーを設定したい

まずはマテリアルの種類を取得できるようにする。

import bpy
import math

# シーンすべてのマテリアルを取得
def frame_scale():
    objects = bpy.data.materials
    mats = list()
    for obj in objects:
        if obj.name != 'Dots Stroke':
            mats.append(obj.name)

frame_scale()

次に前書いたコードの次に動かせるよう調整する。

import bpy
import math
import random

# シーンすべてのマテリアルを取得
def frame_scale():
    objects = bpy.data.materials
    mats = list()
    for obj in objects:
        if obj.name != 'Dots Stroke':
            mats.append(obj.name)
    
    objects = bpy.data.objects

    for obj in objects:
        # オブジェクトの種類が立方体の場合は選択
        if obj.type == 'MESH':
            ob = bpy.data.objects[obj.name]
            rand = random.randint(0,len(mats)-1)
            print(rand)
            ob.data.materials.append(bpy.data.materials[mats[rand]])

frame_scale()

謎に'Dots Stroke'なるマテリアルが存在していたので排除した。
上記コードで一応マテリアル自動付与できるけど、なぜかvalue errorをはく。
最終的にはこんな感じにできた。

https://yuuuha.hatenablog.com/entry/pythonapi-material_more_basic
https://yuni-wiki.com/blender/how_to_get_a_material_data_by_name/