🕳️

[Blender]複数のくり抜き(ブーリアン)を簡単に実施するPythonスクリプト

2022/07/02に公開

たくさん穴が開いたオブジェクトを簡単に作りたい

3Dプリンターでレゴ互換パーツを作っています。レゴ互換パーツの3Dモデルの作成は Blender を使っています。例えばこれはラズパイを設置できるレゴ互換パーツです。こんなのを作っています。

この3Dモデルは以下のように円柱の3Dモデルでくり抜き(ブーリアン)をいくつも実施しています。

円柱のくり抜きは1つづつ実施していて超面倒なのでスクリプトでまとめて実行するようにしたいと思います。

ちなみに、Blender初心者です。

参考にしたサイト

他にもいろいろサイトをみたのですがリンク忘れました。

環境

Windows11
Blender 3.1.2

BlenderのコンソールでPythonバージョンを確認

>>> import sys
>>> sys.version
'3.10.2 (main, Jan 27 2022, 08:34:43) [MSC v.1928 64 bit (AMD64)]'

Blender Pythonスクリプトの書き方

Blenderの Scripting をクリックするとPythonスクリプトを記載する領域(図の緑破線)が表示されます。

サンプル①:くり抜き(ブーリアン)のPythonスクリプト

立方体をトーラス(ドーナツ)でくり抜きしたスクリプトです。

↓の図の左がスクリプトの実行結果です。図の右はくり抜いたトーラス(ドーナツ)を非表示→表示に変更した状態です。

サンプル①_くり抜き(ブーリアン)
import bpy

# 1.既存要素削除
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

# 2.材質の定義(赤色)
mat1 = bpy.data.materials.new('Red')
mat1.diffuse_color = (1.0, 0.0, 0.0, 1.0)

# 3.材質の定義(青色)
mat2 = bpy.data.materials.new('Blue')
mat2.diffuse_color = (0.0, 0.0, 1.0, 1.0)

# 4.立方体
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=1.8, rotation=(0, 0, 0))
bpy.context.object.data.materials.append(mat1) # 材質(赤)指定
ob1 = bpy.context.view_layer.objects.active
ob1.name = "Cube"

# 5.ドーナツ形
bpy.ops.mesh.primitive_torus_add(location=(0, 1, 0), major_radius=1.0, minor_radius=0.5, rotation=(0, 0, 0))
bpy.context.object.data.materials.append(mat2) # 材質(青)指定
ob2 = bpy.context.view_layer.objects.active
ob2.name = "Torus"

# 6.オブジェクトを変数に格納
objects = bpy.data.objects
cube  = objects['Cube']
torus = objects['Torus']

# 7.ブーリアン
bool_two = cube.modifiers.new(type="BOOLEAN", name="bool_01")
bool_two.object = torus
bool_two.operation = 'DIFFERENCE'

bpy.context.view_layer.objects.active = cube
bpy.ops.object.modifier_apply(modifier="bool_01")

# 8.トーラス非表示
bpy.context.view_layer.objects.active = torus
bpy.context.object.hide_set(True)

サンプル②:複数くり抜き(ブーリアン)のPythonスクリプト

サンプル①と同様に立方体をトーラスでくり抜きします。その後に、トーラスを移動し再度立方体をくり抜きます。

↓の図の左がスクリプトの実行結果です。図の右はくり抜いたトーラス(ドーナツ)を非表示→表示に変更した状態です。

サンプル②_複数くり抜き(ブーリアン)
import bpy

# 1.既存要素削除
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

# 2.材質の定義(赤色)
mat1 = bpy.data.materials.new('Red')
mat1.diffuse_color = (1.0, 0.0, 0.0, 1.0)

# 3.材質の定義(青色)
mat2 = bpy.data.materials.new('Blue')
mat2.diffuse_color = (0.0, 0.0, 1.0, 1.0)

mat3 = bpy.data.materials.new('Green')
mat3.diffuse_color = (0.0, 1.0, 0.0, 1.0)

mat4 = bpy.data.materials.new('Yellow')
mat4.diffuse_color = (1.0, 1.0, 0.0, 1.0)

# 4.立方体
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=1.8, rotation=(0, 0, 0))
bpy.context.object.data.materials.append(mat3) # 材質指定
ob1 = bpy.context.view_layer.objects.active
ob1.name = "Cube"

# 5.ドーナツ形
bpy.ops.mesh.primitive_torus_add(location=(0, 1, 0), major_radius=1.0, minor_radius=0.5, rotation=(0, 0, 0))
bpy.context.object.data.materials.append(mat4) # 材質指定
ob2 = bpy.context.view_layer.objects.active
ob2.name = "Torus"

# 6.オブジェクトを変数に格納
objects = bpy.data.objects
cube  = objects['Cube']
torus = objects['Torus']

# 7.ブーリアン
bool_two = cube.modifiers.new(type="BOOLEAN", name="bool_01")
bool_two.object = torus
bool_two.operation = 'DIFFERENCE'

bpy.context.view_layer.objects.active = cube
bpy.ops.object.modifier_apply(modifier="bool_01")

# 8.トーラスを移動
bpy.context.view_layer.objects.active = torus
torus.location = ( 1.2, -1.2, 0 )

# 9.ブーリアン
bool_two = cube.modifiers.new(type="BOOLEAN", name="bool_01")
bool_two.object = torus
bool_two.operation = 'DIFFERENCE'

bpy.context.view_layer.objects.active = cube
bpy.ops.object.modifier_apply(modifier="bool_01")

# 10.トーラス非表示
bpy.context.view_layer.objects.active = torus
bpy.context.object.hide_set(True)

サンプル②スクリプトの一部を関数にする

サンプル③の前にサンプル②スクリプトを少し変えて、『7.ブーリアン』『8.トーラスを移動』『9.ブーリアン』『10.トーラス非表示』の処理を関数にします。

サンプル②スクリプトの一部を関数にする
##-----------##
# (関数)ブーリアン
def booleanFnc(obj01 , obj02):
    bool01 = obj01.modifiers.new(type="BOOLEAN", name="bool_01")
    bool01.object = obj02
    bool01.operation = 'DIFFERENCE'
    bpy.context.view_layer.objects.active = obj01
    bpy.ops.object.modifier_apply(modifier="bool_01")

# (関数)オブジェクト移動
def moveFnc(obj01, mX, mY, mZ):
    bpy.context.view_layer.objects.active = obj01
    obj01.location = ( mX, mY, mZ )

# (関数)オブジェクト非表示
def hideFnc(obj01, setVal):
    bpy.context.view_layer.objects.active = obj01
    bpy.context.object.hide_set( setVal )
##-----------##

# 7.ブーリアン
booleanFnc(cube , torus)

# 8.トーラスを移動
moveFnc(torus, 1.2 , -1.2 , 0)

# 9.ブーリアン
booleanFnc(cube , torus)

# 10.トーラス非表示
hideFnc(torus, True)

サンプル③:ループ処理を使った複数くり抜き(ブーリアン)のPythonスクリプト

サンプル②での複数くり抜きをループ処理で実施します。
実行すると↓の図のようにトーラスで4回くり抜いたオブジェクトが完成します。

サンプサンプル③_ループ処理を使った複数くり抜き(ブーリアン)
import bpy

# 1.既存要素削除
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

# 2.材質の定義(赤色)
mat1 = bpy.data.materials.new('Red')
mat1.diffuse_color = (1.0, 0.0, 0.0, 1.0)

# 3.材質の定義(青色)
mat2 = bpy.data.materials.new('blue')
mat2.diffuse_color = (0.0, 0.0, 1.0, 1.0)
mat3 = bpy.data.materials.new('Green')
mat3.diffuse_color = (0.0, 1.0, 0.0, 1.0)
mat4 = bpy.data.materials.new('Yellow')
mat4.diffuse_color = (1.0, 1.0, 0.0, 1.0)

# 4.立方体
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=1., rotation=(0, 0, 0))
bpy.context.object.data.materials.append(mat4)  #材質指定
bpy.ops.transform.resize(value=(10.0,20.0,0.8)) #図形変形
ob1 = bpy.context.view_layer.objects.active
ob1.name = "Cube"

# 5.ドーナツ形
bpy.ops.mesh.primitive_torus_add(location=(0, 1, 0), major_radius=1.0, minor_radius=0.5, rotation=(0, 0, 0))
bpy.context.object.data.materials.append(mat1) #材質指定
ob2 = bpy.context.view_layer.objects.active
ob2.name = "Torus"

# 6.オブジェクトを変数に格納
objects = bpy.data.objects
cube  = objects['Cube']
torus = objects['Torus']

##-----------##
# (関数)ブーリアン
def booleanFnc(obj01 , obj02):
    bool01 = obj01.modifiers.new(type="BOOLEAN", name="bool_01")
    bool01.object = obj02
    bool01.operation = 'DIFFERENCE'
    bpy.context.view_layer.objects.active = obj01
    bpy.ops.object.modifier_apply(modifier="bool_01")

# (関数)オブジェクト移動
def moveFnc(obj01, mX, mY, mZ):
    bpy.context.view_layer.objects.active = obj01
    obj01.location = ( mX, mY, mZ )

# (関数)オブジェクト非表示
def hideFnc(obj01, setVal):
    bpy.context.view_layer.objects.active = obj01
    bpy.context.object.hide_set( setVal )
##-----------##

pnt = [-2,-2,0] # (x,y,z)

for num in range(4):
    pnt[0] += num
    pnt[1] += num
    moveFnc(torus, pnt[0] , pnt[1] , pnt[2])    # 7.トーラスを移動
    booleanFnc(cube , torus)    # 8.ブーリアン

hideFnc(torus, True)    # 9.トーラス非表示

サンプル④:座標指定で複数くり抜き(ブーリアン)のPythonスクリプト

サンプル③ではオブジェクトの移動を現在位置からX,Y軸方向に1増加した位置に移動していました。今回は、移動先の座標を指定しています。移動先の座標はリスト型の変数 pnts に格納しています。

↓の図はスクリプトの実行結果です。

サンプル④:座標指定で複数くり抜き(ブーリアン)
import bpy

# 1.既存要素削除
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

# 2.材質の定義(赤色)
mat1 = bpy.data.materials.new('Red')
mat1.diffuse_color = (1.0, 0.0, 0.0, 1.0)

mat2 = bpy.data.materials.new('blue')
mat2.diffuse_color = (0.0, 0.0, 1.0, 1.0)

mat3 = bpy.data.materials.new('Green')
mat3.diffuse_color = (0.0, 1.0, 0.0, 1.0)

mat4 = bpy.data.materials.new('Yellow')
mat4.diffuse_color = (1.0, 1.0, 0.0, 1.0)

# 3.立方体
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=1., rotation=(0, 0, 0))
bpy.context.object.data.materials.append(mat1)  #材質指定
bpy.ops.transform.resize(value=(8.0,10.0,0.8)) #図形変形
ob1 = bpy.context.view_layer.objects.active
ob1.name = "Cube"

# 4.円柱
bpy.ops.mesh.primitive_cylinder_add(location=(-5, 5, 0), radius=0.3, depth=3, rotation=(0, 0, 0))
bpy.context.object.data.materials.append(mat2) #材質指定
ob2 = bpy.context.view_layer.objects.active
ob2.name = "Cylinder"

# 5.オブジェクトを変数に格納
objects  = bpy.data.objects
cube     = objects['Cube']
cylinder = objects['Cylinder']

##-----------##
# (関数)ブーリアン
def booleanFnc(obj01 , obj02):
    bool01 = obj01.modifiers.new(type="BOOLEAN", name="bool_01")
    bool01.object = obj02
    bool01.operation = 'DIFFERENCE'
    bpy.context.view_layer.objects.active = obj01
    bpy.ops.object.modifier_apply(modifier="bool_01")

# (関数)オブジェクト移動
def moveFnc(obj01, mX, mY, mZ):
    bpy.context.view_layer.objects.active = obj01
    obj01.location = ( mX, mY, mZ )

# (関数)オブジェクト非表示
def hideFnc(obj01, setVal):
    bpy.context.view_layer.objects.active = obj01
    bpy.context.object.hide_set( setVal )
##-----------##

pnts=[
    [-2, -2, 0.4],
    [-2, -1, 0.4],
    [-2, -0, 0.4],
    [-1, -2, 0.4],
    [-1, -1, 0.4],
    [-1,  0, 0.4],
    [ 0, -2, 0.4],
    [ 0, -1, 0.4],
    [ 0,  0, 0.4],
    [ 1, -2, 0.4],
    [ 1, -1, 0.4],
    [ 1,  0, 0.4],
]

for pnt in pnts:
    moveFnc(cylinder, pnt[0] , pnt[1] , pnt[2]) # 6.トーラスを移動
    booleanFnc(cube , cylinder)                 # 7.ブーリアン

hideFnc(cylinder, True)    # 8.トーラス非表示

ここで紹介したスクリプトを応用してレゴ互換の3Dオブジェクトをスクリプトの実行ボタンを押すだけで作れるようになりました。

https://youtu.be/K2nLRPWj7lM

作成した3Dオブジェクトを3Dプリンターで造形しました。

ラズパイが設置でき、レゴとの互換性も問題なさそうです。

Discussion