Blempy: easy and fast access to Blender attributes

While writing about the foreach_get()/foreach_set() methods and the advantages of using numpy, I realized that we often need a lot of boiler plate code just to access attributes in this way.

This was especially obvious when looking at some old code that deals with a lot of mesh attributes. In hindsight the code for that add-on isn´t all that well-structured1, partly because is needs access to all kinds of attributes.

So long story short, I decided to create a little package to streamline access to attributes and in that way make the code more readable and easier to maintain. The result is a work-in-progress, a package called blempy (a portmanteau of Blender and Numpy2)

1 Although to be fair, it is also more than 9 years old and saw numerous updates. 
2 Yes, I don´t have any imagination.


An example

Perhaps the most inconvenient sets of attributes are those that are connected to loops, i.e. face corners. Examples are uv coordinates and vertex colors and they are that inconvenient to work with because the attributes themselves are stored separately from the other face data.

To access them we would need to download three separate arrays of data: the loop_start and loop_total attribute associated with each polygon (face), and the actual data itself. If we want to access that loop data for a specific polygon, we would need to get the loop_start and loop_total attributes for that polygon to calculate the range of indices into the actual array of attributes, which is quite a bit of code.

The LoopVectorAttributeProxy class abstracts all that away and takes care of downloading everything needed as numpy arrays. The API is currently quite bare, but it does already provide a convenient iterator to access all the loops of a polygon in one go.

For example, to set a unique, but uniform grey value for each face we would need only a handful lines of code (the code assumes that the mesh variable points to a valid bpy.types.Mesh):

from blempy import LoopVectorAttributeProxy proxy = LoopVectorAttributeProxy(mesh, "vertex_colors.active.data", "color") proxy.get() for loops in proxy: grey = random() loops[:] = [grey, grey, grey, 1.0] proxy.set()

As shown, we first create a proxy for the active vertex color layer, and specifically its color attribute, and we then retrieve all the necessary data with the get() method, that will store everything behind the scenes as numpy arrays.

We then get, for each polygon, an array with all the colors for all the loops associated with that polygon, and get some random grey value as well. We then assign the same color (i.e. a list of RGBA values) to all those loop colors. Numpy will take care both of converting the python list to a numpy array as well as broadcasting that same RGBA array to all items in the loops array. By assigning the same color to all vertex corners (loops) in a polygon, that polygon will have a uniform color.

And finally we copy everything back to the mesh object.

Future development

As mentioned, the whole package is a little bare bones still, but I hope the extend its functionality in the near future. In particular I would like to create some classes that can simply be initialized with a Mesh (or even a BMesh) and a unified attribute name, to get rid of even more boiler plate. That and some more convenience functions to manipulate specific types of attributes, like (position) vectors, normals, uv-coordinates, etc.

Suggestions are welcome by the way, just create an issue in the the repository so that we can discuss it. Don´t forget to add the blempy label so it can be distinguished from any other issue.

Installation

blempy is available as a package on pypi and can be installed in the usual way:

python -m pip install blempy

But that would install the package in the default location. That is fine if you use Blender as a module, but if your are developing for the "complete" Blender, you would need to install it inside your Blender environment. A refresher on how to do that can be found in this old article.

If you are developing an addon that uses the blempy package, it is probably easiest to bundle it with your add-on, i.e. simply copy the blempy folder from the repository into your own project. By copying, you automatically fix the version, so that if blempy gets a breaking update you won´t have to deal with that immediately.

No comments:

Post a Comment