A python framework for building 3D environments using Blender.
Developed and tested with Python 3.7 and Blender 2.83.
I once had a need to create a 3D model of an empty room. The model would consist of some walls with windows, a floor and a ceiling. It was chosen to build it using Blender (https://www.blender.org/) a beautiful cross-platform and free 3D modelling software. Moreover, I chose not to create a model "with a mouse", but to program it with the Blender's python API.
As a result, py-blender-room was born, hence the "room" in its name.
py-blender-room offers a workflow to create models and open them in Blender.
Individual models, called projects
, reside in projects
package.
The initial project, named room1
, can be found there. The more models I (or anyone else) need to create, the more sub-packages will appear there.
the entry script of the project is build.py
and it is meant to be interpreted with Blender's built-in Python, as follows:
~/dist/blender-2.83.4-linux64/blender --python py_blender_room/projects/room1/production_build.py
as a result, blender will open with the model as shown in the video below:
tip: if you simply want to validate your script without opening Blender's User Interface, you may run Blender with -b
option.
Scene
holds some objectsSceneRenderer
knows how to get those objects and makeModeler
"materialize" themModeler
is something that implementsModelerInterface
. An example of aModeler
isBlender
. Another example isFakeModeler
which is used in unit tests.
- a scene class
- a scene renderer class
- build.py script
each of these files is described below:
This class, inheriting from Scene
, defines a high-level list of objects.
Objects can be anything: in case of Room1 project, they are "Wall", "Floor" etc. In case of other imaginary projects, they could be "Tree", "Road" and so on.
In a sense, these classes define the domain-specific language you need for your particular project.
The Scene
, in its turn, maintains the list of objects, i.e. those "Walls", "Trees" and "Roads"
The only requirement is that your scene renderer knows how to translate them into the sequence of modeler
instructions.
For example, in case of walls, Room1SceneRenderer knows how to make modeler create Box meshes,
cut out windows, insert "glasses" ang put the whole ensemble into an appropriate position.
Your scene renderer class is a middleware that translates your domain-specific scene objects into instructions modeler understands.
A Modeler is "something" that can build your model, for example, Blender's API is modeler. In the framework, modeler is
represented with a class implementing ModelerInterface
.
note: if you want to use certain feature of blender that wasn't used before, you might want to extend that interface.
This is an entry script:
def run():
scene = Room1Scene()
scene.build()
modeler = Blender()
scene_renderer = Room1SceneRenderer()
scene_renderer.modeler = modeler
scene_renderer.render(scene)
above is a real working example from Room1
project.
The build script:
- instantiates a scene
- invokes a
build
method of the scene - creates a modeler
- for Blender, just use
Blender()
- for Blender, just use
- instantiates a scene renderer
- connects a scene renderer with a modeler
- renders the scene
There is a workflow set up to smoke-test the code in two ways:
- by unit-testing with FakeModeler
- by building "Room1" model using dockerized blender (https://hub.docker.com/repository/docker/hq9000/blender)
currently, Blender 2.83 is supported and tested.