Manipulate objects using Blender 2.8's low-level Python API

This article is the 24th day article of Nextremer Advent Calendar 2019 (although it is late).

Summary

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.

Operating environment

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

Create an object

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).

blender-01.png

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)).

Imagine a little about the inside

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.

Display characters in color

#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.

Put a lot of () (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

Manipulate objects using Blender 2.8's low-level Python API
[S3] CRUD with S3 using Python [Python]
Manipulate spreadsheets locally using Python
Blender Python API in Houdini (Python 3)
Data acquisition using python googlemap api
[Python3] Google translate google translate without using api
Try using Pleasant's API (python / FastAPI)
Validate JSON objects using Python DictShield
Try using Python argparse's action API
Run Ansible from Python using API
Mouse operation using Windows API in Python
Try using the Kraken API in Python
Tweet using the Twitter API in Python
I tried using UnityCloudBuild API from Python
Creating Google Spreadsheet using Python / Google Data API
Procedure to use TeamGant's WEB API (using python)
[Python] Get all comments using Youtube Data API
Try using the BitFlyer Ligntning API in Python
Get image URL using Flickr API in Python
Let's judge emotions using Emotion API in Python
Recent ranking creation using Qiita API with Python
Anonymous upload of images using Imgur API (using Python)
Find polynomial approximations using TensorFlow 2.x Low-level API
Try using ChatWork API and Qiita API in Python
Try using the DropBox Core API in Python
Blender 2.9 Python Extrude extrude
Start using Python
Scraping using Python
Upload JPG file using Google Drive API in Python
Initial settings when using the foursquare API in python
Push notifications from Python to Android using Google's API
Get LEAD data using Marketo's REST API in Python
[Blender] Complement Blender's Python API with a text editor
[Question] About API conversion of chat bot using Python
Send and receive Gmail via the Gmail API using Python
Register a ticket with redmine API using python requests
[Python] Using Line API [1st Creation of Beauty Bot]
OpenVINO using Inference Engine Python API in PC environment
Copy S3 files from Python to GCS using GSUtil
Speech transcription procedure using Python and Google Cloud Speech API
Using the National Diet Library Search API in Python
Speech file recognition by Google Speech API v2 using Python
A little bit from Python using the Jenkins API