It's an article about creating a star system (looks like) arrangement with a Blender script that everyone loves. Fully compatible with Blender 2.80!
Basically, it is a script that rotates iterations and places a large amount on an object, but this time we are also setting materials.
For the time being, from a simple code. Let's arrange the primitive spheres automatically.
import bpy
import numpy as np
#Reset the status quo
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 that produces a sphere
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))
If you set a ring for each sphere that passes through the sphere with the origin as the center, it looks like a star system. Originally, the coordinates were specified by x
and y
, but for the sake of future calculation, the coordinates are specified by the polar coordinates of r
and theta
.
import bpy
import numpy as np
#Reset the status quo
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 that produces a sphere
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):
#Calculated in polar coordinates
r = np.random.rand()*number*10+10
theta = np.random.rand()*np.pi*2
x = r*np.cos(theta)
y = r*np.sin(theta)
#This is a planet
bpy.ops.mesh.primitive_uv_sphere_add(radius=np.random.rand()+1,location=(x,y,0))
#This is the orbit
bpy.ops.mesh.primitive_torus_add(major_radius=256,minor_radius=.1)
bpy.context.object.scale = (r/256,r/256,1)
Here, the API of bpy.ops.mesh.primitive_torus_add
is used. The reference is here. The radius of the donut ring is specified by major_radius
, and the radius of the cross section of the donut is specified by minor_radius
. The reason why major_radius
is set to 0 here is that there is an unclear specification that ** 257 or more cannot be specified with this API ** (I was addicted to it at first), so I chose a donut with a radius of 256. By scaling with bpy.context.object.scale
, it fits to r
.
This time we will also set the material. Since becoming Blender 2.80, shaders have become almost indispensable when setting materials, but ** I have not caught up with script study so much **, so this time I will explain in a mode that does not use shaders. I will. When setting the material with the script, after creating the material data with bpy.data.materials.new
, add the material slot to the target object withbpy.ops.object.material_slot_add ()
and add that slot. The flow is to set the material in the target with bpy.context.object.active_material
.
The material reference is here, but when using ** nodes this is just the beginning. **, you need to mess with the API of a finer node. For the time being, we will set it without using nodes this time (mat.use_nodes = False
), so specify only diffuse_color
, metallic
, and roughness
with random numbers.
This is the display in GUI. Note that this display also changes depending on the render engine, and the above figure is for Cycles
.
import bpy
import numpy as np
#Reset the status quo
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 that produces a sphere
number = 10
#Only the orbital material is set first
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)
#This is a planet
bpy.ops.mesh.primitive_uv_sphere_add(radius=np.random.rand()+1,location=(x,y,0))
#Set individual materials for the planet
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
#This is the orbit
bpy.ops.mesh.primitive_torus_add(major_radius=100,minor_radius=.1)
bpy.context.object.scale = (r/100,r/100,1)
#Apply the previously set trajectory material
mat = bpy.data.materials['orbit']
bpy.ops.object.material_slot_add()
bpy.context.object.active_material=mat
Since it's a big deal, set the sun (like something) in the center.
Added to the above code
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
Since the radius and position of the planet are specified by random numbers, a different star system-like thing is generated each time the script is turned. Blender's solid display looks good, but let's also render at this time. It's pitch black as it is, so you can set the light in the center, but the fake sun will block the light. Here we manually set the material so that the fake sun itself is shining.
Shader node. We have to get used to this even if we don't like it.
The following is the one rendered with the camera and background set. The background starry sky was borrowed from CG Beginner.
Recommended Posts