This article is the 24th day article of Nextremer Advent Calendar 2019 (although it is late).
Blender is software for creating model data for 3D graphics. The source code is publicly available and is free software licensed under GPL-v3.0. Python is built into Blender as a scripting language, and it seems that UI operations can be automated.
Isn't it possible to create and arrange a lot of objects and play with them, just like doing generative art in Processing? If you look it up with that in mind, the following articles will appear. I'm grateful.
-Python for Blender Cookbook ~ Introduction ~- @KTakahiro1729 --Look at the API --Python script in Blender
By the way, as a method of adding an object, it seems that the method of doing as follows in the console of the Scripting tab of Blender is introduced.
#If you do it with a file`import bpy`Is necessary
>>> bpy.ops.mesh.primitive_cube_add()
{'FINISHED'}
>>>
The return value is {" FINISHED "}
. By the way, if you do this in Blender right after startup, an object called Cube.001
will be added under Scene Collection
> Collection
(because an object called Cube
is already placed). What if I try to change this Cube.001
information afterprimitive_cube_add ()
?
#From a child element of Collection in Scene Collection"Cube.001"Pulled by the name
>>> bpy.data.collections.data.objects['Cube.001']
bpy.data.objects['Cube.001']
By the way, the name Cube.001
will be Cube.002
if you do primitive_cube_add ()
in the presence of Cube.001
. In other words, the name differs depending on the state of the UI. Hmmm, I mean, in normal Python programming, I want you to return the name of the created object with primitive_cube_add ()
.
By the way, it seems that the bpy.obs
module is a ** module that provides UI operations as a function.
If it is. There must be a lower level object creation / manipulation API that is called in the UI manipulation.
In this article, let's play with Blender's low-level object manipulation API.
The content of this article uses the GNU / Linux version of the Blender 2.81 binary distributed on the official Blender website.
$ blender -v
Blender 2.81 (sub 16)
build date: 2019-12-04
build time: 13:48:07
build commit date: 2019-12-04
build commit time: 11:32
build hash: f1aa4d18d49d
build platform: Linux
build type: Release
build c flags: -Wall -Wcast-align -Werror=implicit-function-declaration -Werror=return-type -Werror=vla -Wstrict-prototypes -Wmissing-prototypes -Wno-char-subscripts -Wno-unknown-pragmas -Wpointer-arith -Wunused-parameter -Wwrite-strings -Wlogical-op -Wundef -Winit-self -Wmissing-include-dirs -Wno-div-by-zero -Wtype-limits -Wformat-signedness -Wnonnull -Wuninitialized -Wredundant-decls -Wshadow -Wno-error=unused-but-set-variable -fuse-ld=gold -std=gnu11 -msse -pipe -fPIC -funsigned-char -fno-strict-aliasing -msse2 -D_GLIBCXX_USE_CXX11_ABI=0
build c++ flags: -Wredundant-decls -Wall -Wno-invalid-offsetof -Wno-sign-compare -Wlogical-op -Winit-self -Wmissing-include-dirs -Wno-div-by-zero -Wtype-limits -Werror=return-type -Wno-char-subscripts -Wno-unknown-pragmas -Wpointer-arith -Wunused-parameter -Wwrite-strings -Wundef -Wformat-signedness -Wuninitialized -Wundef -Wmissing-declarations -fuse-ld=gold -std=c++11 -msse -pipe -fPIC -funsigned-char -fno-strict-aliasing -msse2 -D_GLIBCXX_USE_CXX11_ABI=0
build link flags: -Wl,--version-script='/home/sources/buildbot-x86_64-slave/linux_glibc217_x86_64_cmake/blender.git/source/creator/blender.map'
build system: CMake
So let's first summon that Blender monkey Suzanne with a low level API. Do this on the console.
#Create a B Mesh object by importing a module that manipulates the raw mesh information of blender
>>> import bmesh
>>> bm = bmesh.new()
#Set Suzanne mesh data to bm
>>> bmesh.ops.create_monkey(bm)
... #Somehow name vertex data comes out
#The actual BMesh object set to bm
>>> bm
<BMesh(0x7f40f970ba08), totvert=507, totedge=1005, totface=500, totloop=1968>
#Create a mesh object for display, convert B Mesh to mesh and set
>>> mesh = bpy.data.meshes.new('suzanne')
>>> bm.to_mesh(mesh)
>>> bm.free() #If you make a lot, you should release it
#For display*object*objectをmeshを指定して作成する
>>> obj = bpy.data.objects.new('suzanne', mesh)
#Link (register) to the object list of the collection in the current context (displayed as)
>>> bpy.context.collection.objects.link(obj)
As a result, it looks like this (the box that was placed by default is deleted).
By the way, you can summon Suzanne as a UI operation with bpy.ops.mesh.primitive_monkey_add ()
(API doc From # bpy.ops.mesh.primitive_monkey_add)).
From the above operations and the Python API documentation (https://docs.blender.org/api/current/bpy.types.html and https://docs.blender.org/api/current/bmesh.html), somehow You can guess something like Blender's data model.
--Objects that can directly edit vertex data (BMesh) and objects that are actually used in Blender (Mesh and Text) are separated.
--The BMesh object seems to follow the C API used by Blender's own mesh editing tools ...?
--Objects are bpy.data
such as bpy.data.objects
and bpy.data.lights
([BlendData Fields](https://docs.blender.org/api/current/bpy.types. BlendData.html)) will be visible to Blender when link (obj)
is done
--The internal state of Blender's application is kept in bpy.context
--Blender's object pool is each field of bpy.data
. Included by type
--The base class of Blender objects is bpy_struct
--Sometimes there is a class that inherits the ʻID class other than
bpy_struct. --An instance of this class can be passed to the second argument of
bpy.data.objects.new (name, object_data) --For example,
TextCurvehttps://docs.blender.org/api/current/bpy.types.TextCurve.html --For example,
Text https://docs.blender.org/api/current/bpy.types.Text.html ――But if you try to create an instance as it is, an error will occur. --Guess: The inside of Blender is made with Entity Component System architecture, and ʻID
corresponds to Entity and component ...?
It may be fun to read the source code to see how it is made.
#Load font
font = bpy.data.fonts.load('/home/grey/.fonts/en/Nobile/Nobile-Regular.ttf')
#Create a collection
col = bpy.data.collections.new('nils')
bpy.context.scene.collection.children.link(col)
#Material to set for the object(color=black)Prepare
mat = bpy.data.materials.new(name="black")
mat.diffuse_color = (0, 0, 0, 1.0)
#Create a FontCurve object
text_curve = bpy.data.curves.new(type='FONT', name='fontcurve')
nil = bpy.data.objects.new('nil', text_curve)
#Set the character string body, font and material
nil.data.body = 'nil'
nil.data.font = font
nil.data.materials.append(mat)
#A function that places characters by specifying an angle or location
def put_nil(x, y, z):
obj = nil.copy()
obj.location = (x, y, z)
obj.rotation_euler = (0, 0, PI/2)
col.objects.link(obj)
#Actually put the letters
put_nil(0, 0, 0)
The result is here.
()
(empty list)#A function that just arranges a lot of nil
def nils(xr, yr, zr):
for x in xr:
for y in yr:
for z in zr:
put_nil(x, y, z)
#It's already a lot of empty lists
nils(
[x/1.1 for x in range(-6, 6)],
[y/1.8 for y in range(-5, 7)],
[z/15 for z in range(-5, 5)]
)
If you do this for the part that calls the put_nil ()
function, you will have a Circle cut image created for Technical Book 8.
Recommended Posts