2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Blender2.80のスクリプトで恒星系を生み出す

Last updated at Posted at 2019-11-26

untitled.png

 みんな大好きBlenderスクリプトで恒星系(のように見える)配置を生み出そうという記事です。Blender2.80完全対応!

 基本的にはイテレーションを回して物体に大量に配置する系のスクリプトですが、今回はマテリアルの設定などもしています。

1. 球体を大量に配置

 とりあえず簡単なコードから。プリミティブの球体を自動的に並べてみます。

image.png

import bpy
import numpy as np

#現状をリセット
for mat in bpy.data.materials:
    bpy.data.materials.remove(mat)
for obj in bpy.data.objects:
        bpy.data.objects.remove(obj)
for obj in bpy.context.scene.objects:
    bpy.data.objects.remove(obj)

#球体を生み出す数
number = 10

for i in range(number):
    x = np.random.rand()*number*10-50
    y = np.random.rand()*number*10-50
    bpy.ops.mesh.primitive_uv_sphere_add(radius=np.random.rand()+1,location=(x,y,0))

2. なんちゃって惑星軌道を追加

 それぞれの球体に、原点を中心としてその球体を通るようなリングを設定したら、なんとなく恒星系のようになりそうです。元々xyで座標を指定していましたが、今後の計算の簡便のため、rthetaの極座標で座標をします。

image.png

import bpy
import numpy as np

#現状をリセット
for mat in bpy.data.materials:
    bpy.data.materials.remove(mat)
for obj in bpy.data.objects:
        bpy.data.objects.remove(obj)
for obj in bpy.context.scene.objects:
    bpy.data.objects.remove(obj)

#球体を生み出す数
number = 10

bpy.data.materials.new(name = 'orbit')
mat = bpy.data.materials['orbit']
mat.use_nodes = False
mat.diffuse_color = (1,1,0,1)

for i in range(number):
    #極座標で計算
    r = np.random.rand()*number*10+10
    theta = np.random.rand()*np.pi*2
    x = r*np.cos(theta)
    y = r*np.sin(theta)

    #こっちは惑星
    bpy.ops.mesh.primitive_uv_sphere_add(radius=np.random.rand()+1,location=(x,y,0))
    
    #こっちは軌道
    bpy.ops.mesh.primitive_torus_add(major_radius=256,minor_radius=.1)
    bpy.context.object.scale = (r/256,r/256,1)

 ここではbpy.ops.mesh.primitive_torus_addのAPIを用いています。リファレンスはここ。ドーナツの輪の半径をmajor_radius、ドーナツの断面の半径をminor_radiusで指定しています。ここでmajor_radiusを0としているのは、なぜかこのAPIでは257以上の値を指定できないというよくわからない仕様があるせいで(最初わからなくてハマった)、半径256のドーナツをbpy.context.object.scaleによって拡大縮小することでrに合わせるという風にしています。

3. マテリアルの指定

image.png

 今回はマテリアルも設定していきます。Blender2.80になってから、マテリアルを設定する場合はほぼシェーダ必須となってしまいましたが、そこまでスクリプトの勉強が追い付いていないので今回はシェーダ使わないモードで解説させていただきます。スクリプトでマテリアルを設定する場合、bpy.data.materials.newでマテリアルのデータを作成した後、対象オブジェクトにbpy.ops.object.material_slot_add()でマテリアルスロットを追加し、そのスロットを対象にbpy.context.object.active_materialでそのマテリアルを設定する、という流れになります。

 マテリアルのリファレンスはここですが、ノードを使う場合これは序の口であって、更に細かいノードのAPIをいじる必要があります。とりあえず今回はノードを使わない設定でいくので(mat.use_nodes = False)、この中のdiffuse_colormetallicroughnessだけ乱数で指定していきます。

image.png

 GUIで言うとこの表示になります。なおこの表示はレンダーエンジンによっても変わり、上の図はCyclesのものになります。

import bpy
import numpy as np

#現状をリセット
for mat in bpy.data.materials:
    bpy.data.materials.remove(mat)
for obj in bpy.data.objects:
        bpy.data.objects.remove(obj)
for obj in bpy.context.scene.objects:
    bpy.data.objects.remove(obj)

#球体を生み出す数
number = 10

#軌道のマテリアルだけ先に設定
bpy.data.materials.new(name = 'orbit')
mat = bpy.data.materials['orbit']
mat.use_nodes = False
mat.diffuse_color = (1,1,0,1)

for i in range(number):
    r = np.random.rand()*number*10+10
    theta = np.random.rand()*np.pi*2
    x = r*np.cos(theta)
    y = r*np.sin(theta)
    #こっちは惑星
    bpy.ops.mesh.primitive_uv_sphere_add(radius=np.random.rand()+1,location=(x,y,0))

    #惑星の個別のマテリアルを設定
    mat_name = 'material' + str(i)
    bpy.data.materials.new(name = mat_name)
    mat = bpy.data.materials[mat_name]
    mat.use_nodes = False
    mat.diffuse_color = np.random.rand(4)
    mat.diffuse_color[3] = 1
    mat.metallic = np.random.rand()
    mat.roughness = np.random.rand()
    bpy.ops.object.material_slot_add()
    bpy.context.object.active_material=mat

    #こっちは軌道
    bpy.ops.mesh.primitive_torus_add(major_radius=100,minor_radius=.1)
    bpy.context.object.scale = (r/100,r/100,1)

    #前に設定した軌道マテリアルを適用
    mat = bpy.data.materials['orbit']
    bpy.ops.object.material_slot_add()
    bpy.context.object.active_material=mat

#4 太陽(っぽいもの)の作成&レンダリング

 せっかくなので、中心に太陽(っぽいもの)を設定します。

image.png

上のコードに追記
bpy.ops.mesh.primitive_uv_sphere_add(radius=4)
bpy.data.materials.new(name = 'sun')
mat = bpy.data.materials['sun']
mat.use_nodes = False
mat.diffuse_color = (1,.5,0,1)
bpy.ops.object.material_slot_add()
bpy.context.object.active_material=mat

 惑星の半径や位置は乱数で指定しているので、スクリプトを回す度に違う恒星系らしきものが生成されます。Blenderのソリッド表示ではいい感じですが、この際レンダリングもしていきましょう。このままでは真っ暗なので中心にライトを設定してもよいですが、このニセ太陽のせいで光が遮られてしまいます。ここは手動でマテリアルを設定して、このニセ太陽自身が輝いているようにします。

image.png

 シェーダノード。我々はこれに嫌でも慣れていかなければならない。

 以下がカメラや背景等を設定してレンダリングしたもの。背景の星空はCGBeginner様よりお借りしました。

untitled.png

2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?