[PYTHON] Bring your life to life procedurally with Blender scripts

image.png

With Blender's script, we will create something ** like that that was talked about at the Expo. Since it is procedurally generated based on random numbers, it is possible to generate innumerable patterns. Blender version is 2.8.

First stage sphere generation

image.png

import bpy
import numpy as np

#Set the red material here
bpy.data.materials.new(name = 'red')
mat_red = bpy.data.materials['red']
mat_red.use_nodes = False
mat_red.diffuse_color = (1,0,0,1)

#Sphere generation
bpy.ops.mesh.primitive_uv_sphere_add(radius=1,location=(0,0,0))
bpy.ops.object.material_slot_add()
bpy.context.object.active_material=mat_red

We will create a red sphere by generating primitives and specifying simple materials. You can create a UV sphere with bpy.ops.mesh.primitive_uv_sphere_add.

Second stage: Proliferation of spheres

I'd like to create innumerable red spheres, but I feel that life is shining if there is some kind of continuity rather than just doing it with a for statement, so I will implement it using a recursive function. I will decide. A recursive function is a program that creates a copy of itself (super-appropriate). image.png

import bpy
import numpy as np

#Set the red material here
bpy.data.materials.new(name = 'red')
mat_red = bpy.data.materials['red']
mat_red.use_nodes = False
mat_red.diffuse_color = (1,0,0,1)

def add_sphere(r,x,y,z,count):
    if count > 20: #Infinite loop without this
        return
    bpy.ops.mesh.primitive_uv_sphere_add(radius=r,location=(x,y,z))
    bpy.ops.object.material_slot_add()
    bpy.context.object.active_material=mat_red
    add_sphere(r,x+1,y,z,count+1) #Call a copy of yourself
    return

add_sphere(1,0,0,0,1)

The sphere is generated by the function ʻadd_sphere, but the function ʻadd_sphere is also called in this. But it's not exactly the same, it produces a copy that is x by 1 off itself. An infinite loop occurs in which the copy is further shifted by one, and a continuous process can be described simply. This is just a horizontal move, but with a command like ʻadd_sphere (1.1 * r, y, x + 1, z, count + 1) `, it looks like this:

image.png

You can feel the mystery of life.

Stage 3 Add randomness

However, this is too regular and does not shine. Looking at the original material, it seems that a number of red spheres of different sizes are connected to form a ring. After all, it seems that a feeling of life comes out if there is some variation in size. The positions of occurrence of each other should also be shaped so that they grow while barely touching the child from the parent.

image.png

import bpy
import numpy as np #Add numpy import

#Set the red material here
bpy.data.materials.new(name = 'red')
mat_red = bpy.data.materials['red']
mat_red.use_nodes = False
mat_red.diffuse_color = (1,0,0,1)

def add_sphere(r,x,y,z,count):
    if count > 20: #Infinite loop without this
        return
    bpy.ops.mesh.primitive_uv_sphere_add(radius=r,location=(x,y,z))
    bpy.ops.object.material_slot_add()
    bpy.context.object.active_material=mat_red
    #Randomly specify longitude and latitude
    theta = np.random.rand()*np.pi*2
    phi = (np.random.rand()-0.5)*np.pi
    #Specify new coordinates
    nr = r*(0.5 + np.random.rand())#The child's ball is the parent's 0.5 times to 1.5 times
    nx = x+(r+nr)*np.cos(theta)*np.cos(phi)
    ny = y+(r+nr)*np.sin(theta)*np.cos(phi)
    nz = z+(r+nr)*np.sin(phi)
    add_sphere(nr,nx,ny,nz,count+1)#Call a copy of yourself
    return

add_sphere(1,0,0,0,1)

Stage 4 Add eyeballs

I will add a cute eyeball. It would be nice if I could set the texture, but here I will draw only with primitives.

image.png

It's shining a lot. After that, if you arrange the shading a little and render it, you can generate a shining image like the beginning.

The code has a lot of verbose parts, so I've simplified some of them as functions.

import bpy
import numpy as np #Add numpy import

#Writing three material settings is lengthy, so make it a function
def create_material(color_name,r,g,b):
    bpy.data.materials.new(name = color_name)
    mat = bpy.data.materials[color_name]
    mat.use_nodes = False
    mat.diffuse_color = (r,g,b,1)
    return mat

mat_red = create_material('red',1,0,0)
mat_white = create_material('white',1,1,1)
mat_eye = create_material('eye',0,1.5,1)

#Writing three coordinate specifications is long, so it is partially functionalized
def next_params(x,y,z,theta,phi,dist):
    nx = x + dist*np.cos(theta)*np.cos(phi)
    ny = y + dist*np.sin(theta)*np.cos(phi)
    nz = z + dist*np.sin(phi)
    return nx,ny,nz

#It takes a long time to write three UV sphere generations, so it is partially functionalized.
def create_sphere(r,x,y,z,mat):
    bpy.ops.mesh.primitive_uv_sphere_add(radius=r,location=(x,y,z))
    bpy.ops.object.material_slot_add()
    bpy.context.object.active_material=mat
    return

#By the way, angle generation is also functionalized
def create_angular():
    theta = np.random.rand()*np.pi*2
    phi = (np.random.rand()-0.5)*np.pi
    return theta,phi

def add_sphere(r,x,y,z,count):
    if count > 20: #Infinite loop without this
        return
    create_sphere(r,x,y,z,mat_red)
    theta,phi = create_angular()
    nr = r*(0.5 + np.random.rand())
    nx,ny,nz = next_params(x,y,z,theta,phi,r+nr)
    add_sphere(nr,nx,ny,nz,count+1)#Call a copy of yourself
    #Generate white eyes (this is just a function)
    theta,phi = create_angular()
    nx,ny,nz = next_params(x,y,z,theta,phi,r/3)
    create_sphere(0.8*r,nx,ny,nz,mat_white)
    #Generate pupil (this is just a function)
    nx,ny,nz = next_params(x,y,z,theta,phi,r/2)
    create_sphere(0.65*r,nx,ny,nz,mat_eye)
    return

add_sphere(1,0,0,0,1)

Stage 5 Parameter adjustment

You can see a different beauty of life by splitting it in the middle or reducing the size of the child's ball.

image.png

If you are interested, it may be a good idea to play with different parameters. However, please note that if you change around count> 20, the amount of objects may increase exponentially and Blender may freeze depending on how the program is constructed.

Recommended Posts

Bring your life to life procedurally with Blender scripts
[Blender] How to make Blender scripts multilingual
[Blender] How to set shape_key with script
To import your own module with jupyter
Create a devilish picture with Blender scripts
Steps to install your own library with pip
Memo to create your own Box with Pepper's Python
Just add the driver to the shape key with blender
How to create a submenu with the [Blender] plugin
I tried to get started with blender python script_Part 01
I tried to get started with blender python script_Part 02
Single sign-on to your Django application with AWS SSO