OneonetのPyBE

Python,Blender,Excelのいろいろ

Blender x Python pipでのライブラリインストールの方法

BlenderPythonが同時にインストールされているとなんとなくややこしくなるPythonのライブラリ管理。BlenderPythonにインストールする方法のご案内。Blenderのバージョンによってパスが違ってきますのでご注意。現時点最新の3.0だとこうなります。

前準備:
管理者モードのコマンドプロンプトを準備します。

カレントディレクトリ:
C:\Program Files\Blender Foundation\Blender 3.0\3.0\python\bin

コマンド:
python -m pip install [ライブラリ名] -t "C:\Program Files\Blender Foundation\Blender 3.0\3.0\python\lib\site-packages"

f:id:oneonet:20220316161710p:plain

Blender x Python で作るQRコード

URL等の文字列からキューブメッシュでQRコードを作成するスクリプトです。ザクッとQRコードを作ってから、キューブの色、ライティング、カメラアングル等いろいろ変更してみると楽しいと思います。いろいろやってみたところで、カメラアングルのお勧めは真正面からの10度ずらしです。

ロジックとしては、「qrcode」というライブラリでQRコードの画像を生成します。その画像から、位置を指定して色を読み取り、その色に合わせて2色のマテリアルを割り当てることでQRコードを生成しています。生成した画像はどこにも現れません。

簡単にロジックやカスタマイズ箇所をご案内します。

冒頭"QR_BLOCK_SIZE=10"は、QRコードを生成するときの1ブロックのピクセル数です。画像からを解析するときに必要ですが、結果には影響しません。

"QR_CODE"に文字列を指定します。お好きなURLを指定してください。

"mat_b","mat_w"は2色のマテリアルです。黒に該当する色は濃い目の色なら何色でも構いません。濃淡を逆にすると読めないリーダーがあるようです。

forの2重ループで、QR画像から色を読み取り、色に合うマテリアルを適用させています。色やメッシュの形はかなり自由に変更できると思います。また、カメラアングルやライティングもいろいろ試してみると面白いと思います。

#blender 3.0.0で動作確認
import bpy
import qrcode

#全部メッシュの削除
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

QR_BLOCK_SIZE = 10
QR_CODE = "https://oneonet-blog.blogspot.com/"

qr = qrcode.QRCode(box_size=QR_BLOCK_SIZE, border=0)
qr.add_data(QR_CODE)
qr.make()
img = qr.make_image(fill_color="black", back_color="white")
img_size,img_size_dummy = img.size
qr_size = img_size // QR_BLOCK_SIZE

mat_b = bpy.data.materials.new("Black")
mat_b.diffuse_color = (0, 0, 0, 1.0)

mat_w = bpy.data.materials.new("White")
mat_w.diffuse_color = (1, 1, 1, 1.0)

for z in range(qr_size):
    for x in range(qr_size):
        x_pos = x * QR_BLOCK_SIZE+1
        z_pos = z * QR_BLOCK_SIZE+1

        bpy.ops.mesh.primitive_cube_add(location=(x,0,qr_size - z), scale=(0.5, 0.5, 0.5))

        if img.getpixel((x_pos, z_pos)):
            bpy.context.object.data.materials.append(mat_w)
        else:
            bpy.context.object.data.materials.append(mat_b)

f:id:oneonet:20220316161341p:plain

Blender x Python で作る途中で模様が出てくる玉転がし

2000個の玉をぶちまけてくるくる回っているところを見ていると何故か模様が浮かび上がる映像です。玉が転がる状況は好きに作ってもらえばいいですが、床板、ガードレール、大量の玉を配置するスクリプトを張っときます。前準備に特別なことはないので見れば何してるかわかるかと思います。

ポイントは準備ができたらアニメーションをスタートし、お好みのフレームでいったん止めます。そのあとオブジェクトモードになっていることを確認して"C"キーを押します。これによりボックス選択ではなくサークル選択選択モードになりますので、マウスホイールでサイズを調整してから、対象としたいメッシュをまとめて選択します。その後マテリアルプロパティでお好きな設定をした後、"マテリアルを選択物にコピー"を選ぶことで、選択したメッシュに全て同じマテリアルが適用されます。サークルである必要はなく、1つ1つクリックして選択するなりしてください。ポイントはアニメーションを途中で止めてその瞬間にちゃんと見えるように指定するところです。

カメラ、ライトはお好きに設定しましょう。見下ろす感じのアングルがよろしいかと思います。

f:id:oneonet:20220316161152p:plain
f:id:oneonet:20220316161202p:plain

#blender 3.0.0で動作確認
import bpy

#全部メッシュの削除
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

f = 200

#床板
bpy.ops.mesh.primitive_plane_add(size=20, enter_editmode=False, align='WORLD', location=(0, 0, -1), scale=(1, 1, 1))
bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'
bpy.context.object.rigid_body.friction = 0.0

#注ぎ口
bpy.ops.mesh.primitive_plane_add(size=3, enter_editmode=False, align='WORLD', location=(3, 7, 3), scale=(1, 1, 1))
bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'
bpy.context.object.rigid_body.friction = 0.0
bpy.context.object.rotation_euler[1] = -0.5
bpy.context.object.rotation_euler[0] = 0.5

#ガードレール 
for z in range (0,10):
    bpy.ops.mesh.primitive_torus_add(align='WORLD', location=(0, 0, -0.5+z*0.5), rotation=(0, 0, 0), major_radius=10, minor_radius=0.1)
    bpy.ops.rigidbody.object_add()
    bpy.context.object.rigid_body.type = 'PASSIVE'
    bpy.context.object.rigid_body.friction = 0.0
    bpy.context.object.rigid_body.collision_shape = 'MESH'

#注ぎ口の上に落ちる球を積み上げる 3×3を200段
for z in range (0,f*3,3):
    for x in range (0,3):
        for y in range (0,3):
            bpy.ops.mesh.primitive_uv_sphere_add(radius=0.5, enter_editmode=False, align='WORLD', location=(x+2, y+6, z+10), scale=(0.5, 0.5, 0.5))
            bpy.ops.rigidbody.object_add()
            bpy.context.object.rigid_body.collision_shape = 'SPHERE'
            bpy.context.object.rigid_body.friction = 0.0

是非動画をミラーサイトでご覧になってください。
oneonet-blog.blogspot.com

Blender x Python でキューブを使ってマインクラフト風壁紙を自動で作る

画像ファイルを読み込み1ピクセルを1つのキューブでブロックのように積み上げて壁画のようにするスクリプトになります。キューブのサイズ半分だけずらしているので真上から見ても真横から見ても同じ画像です。

処理スピード感は、1ラインにあたるキューブ50コの処理時間が最初の1ライン目は0.1秒ですが、10ライン目2.5秒、50ライン目は16秒、100ライン目は30秒という感じでどんどん遅くなります。5000ピクセル程の小さな画像でも30分ほどかかりました。ということでほどほどのサイズでやってみてください。動画、静止画、スクリプトをご紹介します。どうすると早くなるんでしょうか。

#blender 3.0.0で動作確認
import cv2
import bpy

for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

im = cv2.imread('c:/tmp/picture.jpg')
height, width, channels = im.shape[:3]

for x in range(width):
    for y in range(height):
        b,g,r = im[y,x]
        bpy.ops.mesh.primitive_cube_add(enter_editmode=False, align='WORLD', location=(-(height-y) , x, height-y), scale=(0.5, 0.5, 0.5))
        mat_name = str( hex(r*0x10000+g*0x100+b))
        mat = bpy.data.materials.new(mat_name)
        mat.diffuse_color = (r/256, g/256, b/256, 1.0)
        bpy.context.object.data.materials.append(mat)

f:id:oneonet:20220316160843p:plain

是非動画をミラーサイトでご覧ください。
oneonet-blog.blogspot.com

Blender x Python で作るシンプルなドミノ倒し

物理演算のスゴクわかりやすいサンプルに仕立ててみました。 キーワードでググるとたいていのものは見つけらますが、見慣れない1命令があるとワクワクしますね。resizeで簡単に形を変えられるとは知りませんでした。

スタスタスタと気持ちよく倒れる100コのドミノを再生してみてください。planeのサイズとforカウンタの数を変えればいくらでも大きくできますよ。

f:id:oneonet:20220316160516p:plain

#blender 3.0.0で動作確認
import bpy

for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

bpy.ops.mesh.primitive_plane_add(size=400,  align='WORLD', location=(0, 0, -5), scale=(1, 1, 1))
bpy.context.object.rotation_euler[2] = 0.78

bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'

for i in range (0,100):
    bpy.ops.mesh.primitive_cube_add(location=(-200+i*4, 0, 0), size=1.0 )
    bpy.ops.rigidbody.object_add()
    bpy.ops.transform.resize(value=(1, 4, 10), constraint_axis=(False, True, True))

    if i==0:
        bpy.context.object.rotation_euler[1] = 0.3

こちらのサイトを参考にさせて頂きました。
slicker.me